93 Commits

Author SHA1 Message Date
c41b69badf 0.1.4 2026-09-29 18:11:44 +02:00
4fc3cd5e7e 0.1.4-rc.1 2026-09-29 18:01:37 +02:00
091685af50 0.1.4-beta.1 2026-09-29 15:07:38 +02:00
e4f405ea9d 0.1.4-alpha.3 2026-09-29 14:00:25 +02:00
9b140e85b3 0.1.4-alpha.2.fix.1 2026-09-29 13:36:20 +02:00
ed794d66a0 0.1.4-alpha.2 2026-09-29 11:45:01 +02:00
7f475584d6 0.1.4-alpha.1 2026-09-29 11:33:56 +02:00
fe80dbbb73 0.1.3 2026-09-28 13:04:53 +02:00
a9fba6c5c3 0.1.3-rc.1 2026-09-28 13:00:04 +02:00
3f3de726c2 0.1.3-beta.1 2026-09-28 12:49:31 +02:00
8cbd686f47 0.1.3-alpha.3 2026-09-28 11:32:26 +02:00
1223a705c0 0.1.3-alpha.2 2026-09-28 10:41:03 +02:00
eaa9c399be 0.1.3-alpha.1 2026-09-28 10:28:40 +02:00
585b508578 0.1.2 2026-09-28 01:27:41 +02:00
36b2b2162c 0.1.2-rc.1 2026-09-28 01:21:44 +02:00
4dcb0dd89e 0.1.2-beta.1 2026-09-28 01:03:26 +02:00
226d61b041 0.1.2-alpha.3 2026-09-28 00:05:12 +02:00
8de2daa716 0.1.2-alpha.2.fix.1 2026-09-27 23:12:36 +02:00
17b7ef23a1 0.1.2-alpha.2 2026-09-27 22:44:02 +02:00
6e978bfed8 0.0.1-alpha.3.fix.1 2026-09-27 22:36:07 +02:00
46a159a3bc 0.1.2-alpha.1 2026-09-27 22:27:45 +02:00
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
1e10feba95 0.0.3 2026-09-24 13:28:35 +02:00
ec3a101d9b 0.0.3-rc.1 2026-09-24 13:22:43 +02:00
47114fa96b 0.0.3-beta.1 2026-09-24 11:34:28 +02:00
dee864e22b 0.0.3-alpha.6 2026-09-24 11:26:50 +02:00
584a0d1586 0.0.3-alpha.5 2026-09-24 10:57:10 +02:00
8ad4987d38 0.0.3-alpha.4 2026-09-24 09:50:33 +02:00
b3230b4da9 0.0.3-alpha.3 2026-09-24 09:21:39 +02:00
a8dd8ae349 0.0.3-alpha.2 2026-09-24 06:51:16 +02:00
883e20e3c5 0.0.3-alpha.1.fix.1 2026-09-23 22:11:26 +02:00
3472fe7094 0.0.3-alpha.1 2026-09-23 17:54:34 +02:00
1b37d2752a 0.0.2 2026-09-23 15:57:03 +02:00
3ba513da16 0.0.2-rc.1.fix.1 2026-09-23 15:53:55 +02:00
8272cfe33d 0.0.2-rc.1 2026-09-23 15:39:55 +02:00
d0ac83569f 0.0.2-beta.1.fix.1 2026-09-23 15:35:09 +02:00
0719955875 0.0.2-beta.1 2026-09-23 15:26:40 +02:00
ead2e879ef 0.0.2-alpha.5 2026-09-23 15:20:18 +02:00
368dedbed9 0.0.2-alpha.4.fix.1 2026-09-23 15:11:14 +02:00
70ff272b79 0.0.2-alpha.4 2026-09-23 15:05:35 +02:00
34ac3a9286 0.0.2-alpha.3 2026-09-23 11:35:41 +02:00
5f9b84c980 0.0.2-alpha.2 2026-09-23 11:19:21 +02:00
1a5dd0908c 0.0.2-alpha.1.fix.1 2026-09-23 10:44:34 +02:00
d3f1e13c84 0.0.2-alpha.1 2026-09-23 10:29:23 +02:00
278 changed files with 40698 additions and 60 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: CHANGELOG.md -->
<!-- version: 2 -->
<!-- version: 19 -->
# Changelog Project Governance Rules
@@ -7,6 +7,86 @@ 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.4
- réexamine le `DEFER` historique du skeleton Tauri contre les corpus Games/KSP fournis, confirme les prérequis Web désormais couverts et lève le blocage sans généraliser les choix locaux de ces projets ;
- recentre l’owner `710-TAURI` sur le host, l’orchestration, la configuration, les commandes, permissions et capabilities, les plugins et la frontière d’intégration, tandis que TypeScript, Vite, CSS/Sass, package manager et bindings restent possédés par leurs owners dédiés ;
- matérialise `docs/skeletons/004-TAURI.md` comme specification organisationnelle composable avec la fondation, Rust/Cargo et Web, en laissant identifiants, capabilities, plugins, fenêtres, bundles et plateformes au projet destinataire ;
- confirme qu’aucun template technique Tauri générique, contrat `006-TAURI_VALIDATION.md` ni dry-run de faux projet n’est justifié tant qu’aucune responsabilité réutilisable non couverte n’est démontrée ;
- ajoute un audit réutilisable d’hygiène texte imposant LF, absence de whitespace terminal et exactement une newline finale, et durcit le contrat des archives delta/history pour interdire un répertoire englobant autour des chemins du dépôt ;
- effectue une revue d’horizon de fermeture : la clarification de `SHOULD`, l’autonomie des projets après adoption et la frontière future avec SaseDev Knowledge deviennent la cible `0.1.5`, avant les adoptions Games `0.1.6`, KSP `0.1.7` et les audits Rust `0.1.8`.
## 0.1.3
- réévalue le profil Android contre le corpus Games réel tout en conservant Android neutre vis-à-vis du langage applicatif et en composant Java/Gradle uniquement lorsqu'ils sont réellement présents ;
- clarifie les responsabilités `compileSdk` / `targetSdk` / `minSdk`, l'identité `namespace` / `applicationId`, la configuration locale, le signing et les manifests/resources sans promouvoir les valeurs particulières de Games ;
- borne NDK, ABI et code natif aux projets réellement concernés, distingue compilation native, packaging et preuve runtime, et conserve les choix Rust/JNI/SDL de Games hors du profil Android générique ;
- rend Android Lint explicite, sépare tests JVM, tests instrumentés et smokes device/AVD, et distingue APK/AAB des preuves d'installation ou d'exécution ;
- normalise la compatibilité pages mémoire 16 KB uniquement comme contrainte conditionnelle au code natif, au package et au canal de distribution applicables, sans imposer une version AGP/NDK, un `targetSdk` ou une liste d'ABI universels ;
- confirme que les owners existants `400 + 600 + 610`, complétés par `520` et `522` lorsqu'ils s'appliquent, suffisent sans créer de skeleton Android, template, audit Python, owner JNI/Rust/SDL ou contrat de validation redondant ;
- prépare le réexamen Tauri distinct de `0.1.4` sans lever son `DEFER` par anticipation et conserve l'adoption Games comme cible séparée `0.1.5`.
## 0.1.2
- sépare l'ancien profil combiné Java/Maven/Gradle en trois owners indépendants et composables : `520-JAVA`, `521-MAVEN` et `522-GRADLE`, afin qu'un build tool ne devienne pas implicitement applicable à tout projet Java ;
- clarifie la distinction entre JDK utilisé pour construire, niveau Java du code source et niveau de bytecode/runtime supporté, sans généraliser les versions particulières observées dans Games ;
- formalise pour Gradle l'ownership `settings` / root / modules / propriétés partagées, ainsi que le choix proportionné entre Wrapper et Gradle système avec contrainte effectivement vérifiée ;
- conserve Maven comme spécialisation indépendante et cohérente sans prétendre l'avoir éprouvée par Games ni créer d'artefact Maven en l'absence de corpus réel ;
- conserve l'ancien chemin `520-JAVA_MAVEN_GRADLE.md` uniquement comme bridge documentaire `SUPERSEDED` pour les références historiques et n'ajoute aucun template, skeleton, audit Python ou contrat de validation Java/Maven/Gradle non justifié ;
- maintient les responsabilités AGP, SDK/NDK, ABI/JNI, manifests/resources, packaging/signing et smokes Android dans l'owner Android, dont la réévaluation pratique reste la cible distincte `0.1.3`.
## 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 ;
- explicite l'héritage des métadonnées et lints Cargo, ainsi que les exceptions locales motivées ;
- ajoute deux audits facultatifs et ciblés du style Rust, pour l'espacement des lignes vides et les blocs de constantes racine sans ordre sémantique, sans remplacer Rustfmt ni Clippy ;
- ajoute un audit read-only des headers `file` et `version` des fichiers Markdown gouvernés par PGR ;
- fournit une spécification courte pour rédiger le message manuel de reprise après publication d'une stable.
## 0.0.2
- introduit le modèle de profils PGR avec ownership normatif, applicabilité, composition du général vers le spécifique et overrides bornés ;
- matérialise les familles `500 — languages / ecosystems` et `600 — platforms` sans créer prématurément les familles frameworks ou architecture ;
- ajoute les premiers profils réutilisables `510 — Rust / Cargo`, `520 — Java / Maven / Gradle` et `610 — Android` ;
- formalise notamment les politiques de toolchain/target, dépendances et build, visibilité/API, safety/FFI, structure canonique, compatibilité Android, packaging et niveaux de preuve ;
- ajoute deux audits PGR read-only et monotâches : alignement des tableaux Markdown et existence des cibles de liens Markdown locaux ;
- confirme que Rust/JNI, Web/Vite/WASM, Tauri, C/C++/CMake, PHP/Composer et Python restent différés jusqu'à une release où leur contenu justifie un owner réel.
## 0.0.1
- établit la fondation normative de PGR : force `MUST` / `SHOULD` / `MAY`, hiérarchie des scopes et principe de proportionnalité ;

View File

@@ -1,5 +1,5 @@
<!-- file: README.md -->
<!-- version: 3 -->
<!-- version: 27 -->
# 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` et dispose désormais d’une suite de baselines stables `0.1.x`. La stable `0.1.4` réexamine le domaine Tauri contre les corpus Games/KSP, consolide l’owner `710`, matérialise le skeleton organisationnel `004-TAURI.md`, confirme qu’aucun template technique ni contrat de validation Tauri séparé n’est justifié et ajoute un audit réutilisable d’hygiène texte. La revue d’horizon de fermeture réserve `0.1.5` à la sémantique normative, à l’autonomie des projets après adoption et à la frontière PGR / SaseDev Knowledge avant les adoptions Games `0.1.6` et KSP `0.1.7`.
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 ; les releases suivantes de la série `0.0.x` introduisent progressivement profils technologiques, templates techniques et spécifications de skeletons.
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`. La release `0.1.2` stabilise trois owners indépendants `520-JAVA`, `521-MAVEN` et `522-GRADLE`, clarifie JDK/source/bytecode et l'ownership Gradle, conserve Maven cohérent sans corpus artificiel et maintient les responsabilités Android dans `610-ANDROID.md` pour leur réévaluation distincte en `0.1.3`. La release `0.1.3` stabilise le profil Android générique : séparation des responsabilités SDK et identité applicative, contraintes natives conditionnelles, Android Lint explicite, niveaux de tests distincts, frontières APK/AAB et compatibilité 16 KB liée au code natif et au canal de distribution, sans imposer les versions ou ABI propres à Games. La release `0.1.4` stabilise le domaine Tauri : owner `710` recentré sur host/orchestration/ACL/plugins, skeleton `004` composable avec Rust/Cargo et Web, absence assumée de template technique générique ou de validation Tauri redondante, audit d’hygiène texte réutilisable et handoff vers `0.1.5` pour clarifier la sémantique normative et l’autonomie des projets.
## Entrées principales
@@ -25,6 +25,21 @@ La version courante est définie par [`VERSION`](VERSION). La release `0.0.1` é
- [`docs/architecture/001-PROJECT_PROFILE.md`](docs/architecture/001-PROJECT_PROFILE.md) — profil applicable au dépôt PGR ;
- [`docs/architecture/002-GOVERNANCE_ARCHITECTURE.md`](docs/architecture/002-GOVERNANCE_ARCHITECTURE.md) — architecture du référentiel ;
- [`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/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md`](docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md) — plan historique de la stable `0.1.2` : réévaluation Games, scission Java/Maven/Gradle et maintien d'Android hors scope ;
- [`docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md`](docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md) — plan historique de la stable Android `0.1.3`, fondée sur Games avec classification `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER` ;
- [`docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md`](docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md) — plan historique de la stable Tauri `0.1.4`, du réexamen Games/KSP au skeleton `004`, à la décision d’artefacts et à la revue d’horizon ;
- [`docs/skeletons/004-TAURI.md`](docs/skeletons/004-TAURI.md) — specialization Tauri 2 composable, sans template technique universel ni defaults de capabilities/plugins/fenêtres/bundles ;
- [`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,22 +1,46 @@
<!-- file: ROADMAP.md -->
<!-- version: 2 -->
<!-- version: 17 -->
# 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é.
## Fondation `0.0.x`
- `(x) 0.0.1` — fondation normative et documentaire : gouvernance, lifecycle des releases, rôles documentaires, workflow delta/history/handoff et validation proportionnée ;
- `( ) 0.0.2` — profils de règles par langage, plateforme, framework et type de projet ;
- `( ) 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.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 ;
- `(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 ;
- `(x) 0.1.2` — réévaluation pratique de Java/Maven/Gradle, séparation des owners lorsque leurs applicabilités divergent et matérialisation uniquement des artefacts génériques réellement nécessaires ;
- `(x) 0.1.3` — réévaluation pratique du profil Android existant à partir de Games, sans absorber les décisions propres aux jeux ou à SDL ;
- `(x) 0.1.4` — domaine Tauri : réexamen du `DEFER`, consolidation de l’owner `710`, matérialisation du skeleton contrôlé `004` et décision explicite de ne pas créer d’artefacts techniques redondants ;
- `( ) 0.1.5` — sémantique normative et autonomie : clarifier `MUST / SHOULD / MAY`, rendre explicite l’autorité locale d’un projet après instanciation/adoption et fixer la frontière durable entre PGR et SaseDev Knowledge ;
- `( ) 0.1.6` — adoption réelle de PGR par `sasedev-games` avec mapping `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER`, après stabilisation du contrat d’autonomie ;
- `( ) 0.1.7` — adoption réelle de PGR par `khadhroony-solana-project`, principalement sur Rust/Cargo + Tauri et sans dépendance aux profils non applicables ;
- `( ) 0.1.8` — 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
- `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é.
La revue d’horizon `0.1.4-rc.1` remplace l’ordre initial `0.1.5` Games / `0.1.6` KSP / `0.1.7` audits par le contrat ci-dessus. Une nouvelle revue d’horizon doit intervenir si `0.1.5` démontre que l’autonomie ne peut pas être stabilisée sans scope supplémentaire, ou si Games/KSP exigent un owner réellement préalable à 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: 5 -->
<!-- version: 14 -->
# Index normatif Project Governance Rules
@@ -72,12 +72,29 @@ Les traductions complètes éventuelles vivent dans des dépôts distincts (`pgr
Les règles détaillées sont structurées progressivement sous [`docs/rules/`](docs/rules/).
Famille actuellement active :
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.md`](docs/rules/520-JAVA.md) — profil Java : JDK LTS, compatibilité source/bytecode, structure, packages, API et tests.
- [`docs/rules/521-MAVEN.md`](docs/rules/521-MAVEN.md) — spécialisation Maven : ownership du reactor, wrapper conditionnel, validation et outputs.
- [`docs/rules/522-GRADLE.md`](docs/rules/522-GRADLE.md) — spécialisation Gradle : ownership du build, version/wrapper, DSL, propriétés, validation et outputs.
- [`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).
Une famille de règles n'est créée que lorsqu'elle possède un contenu réel ; aucun répertoire vide n'est requis pour anticiper une future technologie.

View File

@@ -1 +1 @@
0.0.1
0.1.4

View File

@@ -0,0 +1,180 @@
<!-- file: deltas/0.0.2/alpha.1.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.2-alpha.1.fix.1 — correction du cadrage, sizing et audit Markdown
## Baseline
Version attendue avant application :
```text
0.0.2-alpha.1
```
La baseline doit correspondre au commit de `alpha.1` après application de `history/0.0.2/alpha.1.md` en statut `FAIL`.
Version après application :
```text
0.0.2-alpha.1.fix.1
```
## Objet
Corriger exclusivement les défauts identifiés dans le cadrage `alpha.1` avant de commencer `alpha.2` :
- corriger l'alignement source du tableau `Inventaire des profils candidats` ;
- reconnaître la preuve post-tag `publish.001` déjà disponible sans modifier rétroactivement `v0.0.1` ;
- réduire le forecast `0.0.2` à un ensemble de profils compatible avec le sizing d'une session ;
- introduire le premier audit PGR monotâche réellement justifié par un défaut observé ;
- enregistrer cet audit dans la matrice de validation.
Aucune règle technologique détaillée n'est introduite par ce fix.
## Rapport post-tag reconnu
Le rapport externe à la baseline source :
```text
pgr-0.0.1-publish.001-report.md
```
est connu comme preuve post-publication `PASS` de l'archive `pgr-v0.0.1.zip`.
Il ne fait pas partie du tag stable et ne doit pas être copié dans le dépôt rétroactivement.
Le besoin futur d'indiquer automatiquement, dans le handoff/prompt manuel de reprise, si un rapport `publish.*` doit être fourni est conservé comme amélioration de workflow hors scope de `0.0.2`.
## Sizing corrigé
Le forecast actif devient :
```text
alpha.2 Rule profile model
alpha.3 Rust / Cargo
alpha.4 Java / Maven / Gradle
alpha.5 Android
beta.1 Profile reconciliation
rc.1 Rule profiles release candidate
stable 0.0.2
```
Les profils/compositions suivants restent explicitement différés :
```text
Rust + Android / JNI
Web / TypeScript / Vite / WASM / Rust server
Tauri desktop/mobile
C / C++ / CMake
PHP / Composer
Python 3 application/package
```
Leur différé ne vaut ni rejet ni oubli.
## Premier audit PGR matérialisé
Le fichier suivant est ajouté :
```text
scripts/audit_markdown_tables.py
```
Son contrat est volontairement limité :
```text
INPUT
fichiers/répertoires Markdown explicitement fournis
OUTPUT
diagnostics texte
exit code
SIDE EFFECTS
aucun
```
Il vérifie uniquement :
- la reconnaissance des tableaux hors fenced code blocks ;
- le nombre cohérent de colonnes ;
- l'alignement vertical des cellules dans le source ;
- la largeur des séparateurs ;
- le padding conforme à l'alignement Markdown.
Il ne vérifie pas les blank lines, headers `file/version`, liens, orthographe ou responsabilités documentaires. Ces propriétés appartiennent à d'autres contrôles présents ou futurs.
Il utilise uniquement la bibliothèque standard Python et doit être exécuté avec `python3 -B` afin de ne pas créer `__pycache__` ou `.pyc`.
## Scope
REPLACE :
```text
VERSION
docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
scripts/audit_markdown_tables.py
deltas/0.0.2/alpha.1.fix.1.md
```
DELETE : aucun.
Aucun manifest de suppression n'est nécessaire.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2-alpha.1.fix.1"
test -f scripts/audit_markdown_tables.py
test -f deltas/0.0.2/alpha.1.fix.1.md
grep -F '### Preuve post-tag `publish.001`' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -F '### alpha.5 — Android' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -F 'Rust + Android / JNI' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -F '`PGR-MD-TABLE-001`' docs/validation/001-VALIDATION_MATRIX.md
python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md docs/validation/001-VALIDATION_MATRIX.md scripts/audit_markdown_tables.py deltas/0.0.2/alpha.1.fix.1.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history du fix est :
```text
M VERSION
A deltas/0.0.2/alpha.1.fix.1.md
M docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
M docs/validation/001-VALIDATION_MATRIX.md
A scripts/audit_markdown_tables.py
```
Revue opérateur complémentaire :
- confirmer que le tableau `Inventaire des profils candidats` est lisible et aligné dans le source ;
- confirmer que le report `publish.001` est traité comme preuve post-tag externe et non comme fichier manquant du tag ;
- confirmer que le scope réduit reste suffisamment représentatif sans chercher à matérialiser les profils différés ;
- confirmer que l'audit Python est read-only et monotâche ;
- confirmer qu'aucune règle technologique de `alpha.2+` n'a été introduite.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/alpha.1.fix.1.md`, committer le fix, puis seulement préparer `0.0.2-alpha.2` consacré au modèle de profils.
### FAIL
Rester dans `0.0.2-alpha.1.fix.M`. À partir de `.fix.3`, réexaminer obligatoirement le plan et la nécessité d'un REPLAN conformément aux règles PGR.

171
deltas/0.0.2/alpha.1.md Normal file
View File

@@ -0,0 +1,171 @@
<!-- file: deltas/0.0.2/alpha.1.md -->
<!-- version: 1 -->
# Delta 0.0.2-alpha.1 — audit de baseline et cadrage des profils
## Baseline
Archive source fournie par l'opérateur comme téléchargement du tag stable Gitea :
```text
v0.0.1
```
Cette archive constitue la baseline autoritaire de la tranche. L'absence de `.git` y est normale ; aucun état provenant d'un workspace local ou d'une conversation antérieure n'est utilisé comme état courant s'il n'est pas confirmé par l'archive ou par `prompts/002-V0_0_2_START_PROMPT.md`.
Version attendue avant application :
```text
0.0.1
```
Version après application :
```text
0.0.2-alpha.1
```
## Objet
Exécuter le gate de framing imposé par le prompt `0.0.2` avant toute consolidation technologique :
- vérifier la baseline stable `v0.0.1` ;
- auditer les règles, la gouvernance, la structure documentaire, les deltas/histories et la cohérence générale ;
- confronter le prompt `0.0.2` à l'état réel du dépôt ;
- inventorier les profils technologiques candidats ;
- limiter le scope aux profils utiles à cette première release ;
- dimensionner les tranches suivantes ;
- créer le plan actif `0.0.2`.
Aucune règle technologique détaillée n'est introduite dans `alpha.1`.
## Résultat de l'audit de baseline
La prévalidation de l'archive a constaté :
- archive ZIP lisible, racine unique `pgr/`, sans doublon, traversal ou symlink ;
- `44` fichiers et `13` répertoires ;
- `VERSION` égal à `0.0.1` ;
- absence normale de `.git` ;
- aucun cache/build connu ou secret local distribué ;
- headers `file/version` cohérents sur tous les Markdown ;
- aucun lien Markdown local cassé parmi les liens vérifiés ;
- `12` deltas et `12` histories `0.0.1` appariés exactement ;
- chaîne PASS/FAIL/fix cohérente jusqu'à `rel.001` PASS ;
- plan `0.0.1` clôturé, roadmap/changelog cohérents et prompt `0.0.2` présent ;
- compteurs internes des documents vivants cohérents avec les opérations de deltas observées.
Aucun défaut bloquant n'impose de `0.0.1` correctif avant le démarrage de `0.0.2`.
Une observation non bloquante est conservée dans le plan : le history stable mentionne un contrôle post-tag `publish.001`, mais aucune preuve versionnée correspondante ne peut être déduite de cette archive. `alpha.1` n'invente ni ne reconstruit cette preuve.
## Cadrage retenu
`0.0.2` matérialisera d'abord :
```text
profile model / composition
Rust / Cargo
Java / Maven / Gradle
Android
Rust + Android / JNI
Web / TypeScript / Vite / WASM / Rust server composition
Tauri desktop/mobile
```
Les profils suivants sont examinés mais différés de cette release afin d'éviter une taxonomie exhaustive sans nécessité immédiate :
```text
C / C++ / CMake
PHP / Composer
Python 3 application/package
```
Ils restent des candidats futurs et ne sont pas rejetés.
Les règles cross-cutting ne recevront un propriétaire `800 — architecture` que lorsqu'une règle réellement commune à plusieurs profils n'est pas déjà possédée par un owner général existant.
## Scope
REPLACE :
```text
VERSION
```
ADD :
```text
docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
deltas/0.0.2/alpha.1.md
```
DELETE : aucun.
Aucun manifest de suppression n'est nécessaire.
## Documents volontairement inchangés
Les documents suivants ne sont pas modifiés uniquement pour refléter le passage à `0.0.2-alpha.1` :
```text
README.md
RULES.md
ROADMAP.md
CHANGELOG.md
docs/000-README.md
docs/rules/000-README.md
```
Leur contenu courant reste cohérent : la roadmap annonce déjà `0.0.2`, les règles possèdent déjà le framing `alpha.1` et la hiérarchie général → spécifique, et le changelog ne journalise pas les prereleases internes.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2-alpha.1"
test -f docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
test -f deltas/0.0.2/alpha.1.md
grep -F 'Plan actif créé pendant `0.0.2-alpha.1`' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -F 'Aucun défaut bloquant de gouvernance' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -F '### alpha.2 — Rule profile model' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -F '### alpha.8 — Tauri desktop/mobile' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -F -- '- `( ) 0.0.2`' ROADMAP.md
grep -F 'v0.0.1' prompts/002-V0_0_2_START_PROMPT.md
git diff --check
git add VERSION docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md deltas/0.0.2/alpha.1.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history est :
```text
M VERSION
A deltas/0.0.2/alpha.1.md
A docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
```
Revue opérateur complémentaire :
- confirmer que l'archive `v0.0.1` utilisée est bien celle téléchargée depuis le tag Gitea déclaré ;
- confirmer que l'absence de `.git` n'est pas traitée comme une anomalie ;
- vérifier que le plan n'introduit aucune règle technologique comme déjà normative ;
- vérifier que les profils différés ne sont ni oubliés ni artificiellement matérialisés ;
- vérifier que `README.md`, `RULES.md`, `ROADMAP.md`, `CHANGELOG.md` et les historiques `0.0.1` ne sont pas modifiés par cette tranche.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/alpha.1.md`, committer `alpha.1`, puis seulement préparer `0.0.2-alpha.2` consacré au modèle documentaire et à la composition des profils.
### FAIL
Rester dans le scope de cadrage avec `0.0.2-alpha.1.fix.1`. Le fix corrige uniquement les défauts du framing/audit/plan ; aucune règle technologique de `alpha.2+` ne doit y être absorbée.

180
deltas/0.0.2/alpha.2.md Normal file
View File

@@ -0,0 +1,180 @@
<!-- file: deltas/0.0.2/alpha.2.md -->
<!-- version: 1 -->
# Delta 0.0.2-alpha.2 — rule profile model
## Baseline
Version attendue avant application :
```text
0.0.2-alpha.1.fix.1
```
Le history `history/0.0.2/alpha.1.fix.1.md` MUST avoir été appliqué et committé avant ce delta.
Version après application :
```text
0.0.2-alpha.2
```
## Objet
Formaliser le modèle de profils PGR avant toute consolidation technologique détaillée.
Cette tranche définit :
- la notion de profil et son propriétaire normatif ;
- l'applicabilité d'un profil à partir de faits réels du projet ;
- la composition du général vers le spécifique ;
- la résolution des overrides et des conflits ;
- la non-duplication des règles héritées ;
- le traitement des spécialisations internes et profils composites ;
- la distinction entre règle décidée et choix encore ouvert ;
- les contrats communs des familles `500 — languages / ecosystems` et `600 — platforms` nécessaires au scope réduit de `0.0.2`.
Aucune règle Rust, Cargo, Java, Maven, Gradle ou Android détaillée n'est encore introduite.
## Modèle retenu
La composition de référence reste :
```text
GENERAL
↓
ecosystem / language
↓
platform
↓
framework
↓
project type / subsystem
↓
project-specific
↓
explicit exception
```
Chaque règle durable possède un seul owner normatif. Les profils spécifiques héritent des règles générales et ne les recopient pas.
Une contradiction volontaire doit être un override explicite, borné et justifié. Deux règles applicables de même niveau qui se contredisent sans relation explicite constituent un défaut à résoudre ; l'ordre des fichiers ne crée aucune priorité.
Les profils composites ne sont créés que si l'intersection de plusieurs profils possède un contrat propre réel. La simple coexistence de deux technologies ne suffit pas.
## Familles activées
`alpha.2` active uniquement les familles nécessaires aux prochaines tranches :
```text
500 — languages / ecosystems
600 — platforms
```
Les familles suivantes restent réservées et non matérialisées :
```text
700 — frameworks
800 — architecture
```
Les règles project-specific continuent d'appartenir au dépôt qui les possède ; PGR ne crée pas de placeholder `900` sans contenu réel.
## Scope
REPLACE :
```text
VERSION
RULES.md
docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
docs/rules/000-README.md
```
ADD :
```text
docs/architecture/003-RULE_PROFILE_MODEL.md
docs/rules/500-LANGUAGES.md
docs/rules/600-PLATFORMS.md
deltas/0.0.2/alpha.2.md
```
DELETE : aucun.
Aucun manifest de suppression n'est nécessaire.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2-alpha.2"
test -f docs/architecture/003-RULE_PROFILE_MODEL.md
test -f docs/rules/500-LANGUAGES.md
test -f docs/rules/600-PLATFORMS.md
test -f deltas/0.0.2/alpha.2.md
grep -F 'Toute règle durable doit posséder un seul propriétaire normatif canonique.' docs/architecture/003-RULE_PROFILE_MODEL.md
grep -F "L'ordre des fichiers dans un répertoire ne crée jamais une priorité normative." docs/architecture/003-RULE_PROFILE_MODEL.md
grep -F 'PGR ne crée pas automatiquement un profil composite pour chaque combinaison possible.' docs/architecture/003-RULE_PROFILE_MODEL.md
grep -F 'Les profils spécifiques utilisent la plage `510` à `599`.' docs/rules/500-LANGUAGES.md
grep -F 'Une spécialisation de build tool ne devient pas une règle du langage entier.' docs/rules/500-LANGUAGES.md
grep -F 'La modernité de la toolchain de build et la version minimale du runtime ou de la target sont deux décisions distinctes.' docs/rules/600-PLATFORMS.md
grep -F 'Les profils spécifiques utilisent la plage `610` à `699`.' docs/rules/600-PLATFORMS.md
grep -F '500-LANGUAGES.md' RULES.md
grep -F '600-PLATFORMS.md' RULES.md
grep -F '003-RULE_PROFILE_MODEL.md' docs/rules/000-README.md
grep -F 'famille `500 — languages / ecosystems`' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION RULES.md \
docs/architecture/003-RULE_PROFILE_MODEL.md \
docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md \
docs/rules/000-README.md \
docs/rules/500-LANGUAGES.md \
docs/rules/600-PLATFORMS.md \
deltas/0.0.2/alpha.2.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history est :
```text
M RULES.md
M VERSION
A deltas/0.0.2/alpha.2.md
A docs/architecture/003-RULE_PROFILE_MODEL.md
M docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
M docs/rules/000-README.md
A docs/rules/500-LANGUAGES.md
A docs/rules/600-PLATFORMS.md
```
Revue opérateur complémentaire :
- confirmer que le modèle permet de déterminer où une règle doit être possédée sans utiliser l'ordre des fichiers comme priorité ;
- confirmer que les spécialisations Maven/Gradle pourront rester locales à Java/build et qu'une contrainte Android ne contaminera pas Java en général ;
- confirmer que les familles `700` et `800` ne sont pas créées prématurément ;
- confirmer qu'aucune règle technologique détaillée prévue pour `alpha.3+` n'a été absorbée dans cette tranche.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/alpha.2.md`, committer la tranche, puis préparer `0.0.2-alpha.3` consacré au premier profil réel `Rust / Cargo`.
`alpha.3` reste le point de mesure prévu par le plan : si le coût réel d'un profil complet invalide le sizing, effectuer un REPLAN avant `alpha.4`.
### FAIL
Rester dans `0.0.2-alpha.2.fix.M` tant que le modèle de profil lui-même n'est pas cohérent. Ne pas commencer le profil Rust/Cargo sur un modèle non validé.

166
deltas/0.0.2/alpha.3.md Normal file
View File

@@ -0,0 +1,166 @@
<!-- file: deltas/0.0.2/alpha.3.md -->
<!-- version: 1 -->
# Delta 0.0.2-alpha.3 — premier profil Rust / Cargo
## Baseline
Version attendue avant application :
```text
0.0.2-alpha.2
```
Le history `history/0.0.2/alpha.2.md` MUST avoir été appliqué et committé avant ce delta.
Version après application :
```text
0.0.2-alpha.3
```
## Objet
Matérialiser le premier profil technologique réel de PGR : `Rust / Cargo`.
Cette tranche sert aussi de point de mesure prévu par le plan `0.0.2`. Elle doit consolider uniquement les règles Rust/Cargo suffisamment générales pour être réutilisables, sans recopier les particularités métier ou les micro-conventions propres à KSP ou `sasedev-games`.
## Réconciliation des corpus sources
Les deux corpus historiques de référence convergent notamment sur :
- l'utilisation d'un workspace Cargo structuré ;
- la centralisation des métadonnées/lints et des dépendances réellement partagées ;
- l'activation locale des features selon le besoin de la crate ;
- une politique Rust stricte autour de `unsafe`, `unwrap`, `expect`, retours explicites et Clippy ;
- une façade de crate explicite plutôt qu'une exposition accidentelle des modules internes ;
- `rustfmt.toml` comme propriétaire du formatage ;
- la séparation des tests unitaires et d'intégration ;
- une gate `fmt` / audit applicable / `check` / `clippy`, avec tests ciblés par défaut et tests workspace aux gates larges ;
- l'absence d'exécution opportuniste de `cargo update`, `cargo tree`, `cargo build` ou `cargo clean` sans besoin correspondant.
La consolidation ne promeut pas automatiquement les divergences ou conventions trop spécifiques :
- l'interdiction KSP de tous les imports `use` non-traits n'est pas élevée au profil Rust général ;
- les micro-règles KSP de lignes vides/ordre interne ne remplacent pas `rustfmt` au niveau PGR ;
- aucune dépendance, crate, version de bibliothèque ou règle Solana/games n'est reprise ;
- la politique historique commune d'ignorer `Cargo.lock` n'est pas rendue universelle : le profil exige une politique explicite selon le type de produit ;
- l'exception `unsafe` Android/JNI de games reste un exemple de spécialisation FFI locale et non une permission Rust générale ;
- le chemin externe des artefacts Cargo n'est pas figé avant les futures règles de skeleton/layout.
## Profil créé
Le nouveau propriétaire normatif est :
```text
docs/rules/510-RUST_CARGO.md
```
Il couvre :
- toolchain et édition ;
- workspace et unités de release ;
- manifests, dépendances et features ;
- politique explicite de `Cargo.lock` ;
- lints communs et safety ;
- API, visibilité et rustdoc ;
- contrôle de flux/erreurs du profil strict ;
- `rustfmt.toml` ;
- `.cargo/config.toml` et artefacts générés ;
- organisation des tests ;
- commandes de validation Rust/Cargo ;
- stratégie future d'audits Rust monotâches.
Aucun script Rust supplémentaire n'est créé dans cette tranche. PGR ne possède actuellement aucun workspace Rust réel à auditer ; introduire maintenant une copie simplifiée des auditeurs games/KSP créerait une gate sans sujet réel. Le premier audit PGR déjà matérialisé reste l'audit Markdown monotâche introduit lorsque son besoin a été observé.
## Scope
REPLACE :
```text
VERSION
RULES.md
docs/rules/000-README.md
```
ADD :
```text
docs/rules/510-RUST_CARGO.md
deltas/0.0.2/alpha.3.md
```
DELETE : aucun.
Aucun manifest de suppression n'est nécessaire.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2-alpha.3"
test -f docs/rules/510-RUST_CARGO.md
test -f deltas/0.0.2/alpha.3.md
grep -F 'PGR MUST NOT imposer un pin exact de toolchain uniquement parce qu' docs/rules/510-RUST_CARGO.md
grep -F 'le fichier PGR `VERSION` reste la version canonique de l' docs/rules/510-RUST_CARGO.md
grep -F 'Une crate membre SHOULD consommer cette dépendance avec `workspace = true`' docs/rules/510-RUST_CARGO.md
grep -F 'PGR ne généralise pas automatiquement la politique de lockfile' docs/rules/510-RUST_CARGO.md
grep -F 'unsafe_code = "forbid"' docs/rules/510-RUST_CARGO.md
grep -F 'PGR ne généralise pas l'"'"'interdiction KSP plus stricte de tous les `use` non-traits' docs/rules/510-RUST_CARGO.md
grep -F 'cargo clippy --workspace --all-targets --all-features -- -D warnings' docs/rules/510-RUST_CARGO.md
grep -F 'PGR SHOULD préférer plusieurs audits monotâches et lisibles' docs/rules/510-RUST_CARGO.md
grep -F '510-RUST_CARGO.md' RULES.md
grep -F '510-RUST_CARGO.md' docs/rules/000-README.md
python3 -B scripts/audit_markdown_tables.py \
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION RULES.md \
docs/rules/000-README.md \
docs/rules/510-RUST_CARGO.md \
deltas/0.0.2/alpha.3.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history est :
```text
M RULES.md
M VERSION
A deltas/0.0.2/alpha.3.md
M docs/rules/000-README.md
A docs/rules/510-RUST_CARGO.md
```
Revue opérateur complémentaire :
- confirmer que le profil distingue bien les règles Rust/Cargo générales des conventions strictement KSP ou games ;
- confirmer que la politique de lockfile reste explicitement project-type-specific et n'est pas généralisée uniquement parce que les deux corpus historiques ignoraient `Cargo.lock` ;
- confirmer que les contraintes FFI/plateforme restent des overrides locaux ;
- confirmer qu'aucune version de crate ou de toolchain historique n'a été recopiée comme pin universel ;
- confirmer qu'aucun audit Rust complexe n'a été ajouté avant d'avoir un sujet réel et une propriété mono-responsabilité à contrôler.
## Point de mesure / REPLAN
`alpha.3` est le point de mesure explicite prévu par le plan.
Le profil Rust/Cargo tient dans une tranche documentaire autonome sans nécessiter de famille supplémentaire, de script d'audit complexe ou de sous-profil framework/plateforme. Le forecast `alpha.4 — Java / Maven / Gradle` reste donc raisonnable à ce stade.
Si la validation de cette tranche révèle au contraire une dérive importante du modèle ou plusieurs corrections substantielles, effectuer un REPLAN avant `alpha.4` plutôt que poursuivre mécaniquement.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/alpha.3.md`, committer la tranche, puis préparer `0.0.2-alpha.4` consacré à `Java / Maven / Gradle`.
### FAIL
Rester dans `0.0.2-alpha.3.fix.M` tant que le premier profil réel ne respecte pas le modèle `alpha.2`. Un défaut de dimensionnement significatif peut déclencher un REPLAN avant toute tranche Java.

View File

@@ -0,0 +1,106 @@
<!-- file: deltas/0.0.2/alpha.4.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.2-alpha.4.fix.1 — cohérence de la gate Java
## Baseline
Version attendue avant application :
```text
0.0.2-alpha.4
```
Le history `history/0.0.2/alpha.4.md` MUST avoir été appliqué avant ce correctif.
Version après application :
```text
0.0.2-alpha.4.fix.1
```
## Objet
Corriger uniquement le défaut de cohérence détecté pendant la gate opérateur de `alpha.4`.
Le profil décrivait déjà la structure Java canonique sous forme d'arbre, mais la validation cherchait littéralement :
```text
src/main/
```
sans que cette chaîne existe telle quelle dans le document.
Le correctif ajoute une phrase explicite listant les chemins canoniques déjà impliqués par l'arborescence :
```text
src/main/java/
src/main/resources/
src/test/java/
src/test/resources/
```
Aucune règle Java, Maven ou Gradle nouvelle n'est introduite.
## Scope
REPLACE :
```text
VERSION
docs/rules/520-JAVA_MAVEN_GRADLE.md
```
ADD :
```text
deltas/0.0.2/alpha.4.fix.1.md
```
DELETE : aucun.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2-alpha.4.fix.1"
test -f docs/rules/520-JAVA_MAVEN_GRADLE.md
test -f deltas/0.0.2/alpha.4.fix.1.md
grep -F 'src/main/java/' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'src/main/resources/' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'src/test/java/' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'src/test/resources/' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'le JDK de développement SHOULD être une version LTS' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'PGR MUST NOT ajouter un Maven Wrapper uniquement par cérémonie.' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'Un Gradle Wrapper SHOULD être versionné lorsqu' docs/rules/520-JAVA_MAVEN_GRADLE.md
python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION docs/rules/520-JAVA_MAVEN_GRADLE.md deltas/0.0.2/alpha.4.fix.1.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history est :
```text
M VERSION
A deltas/0.0.2/alpha.4.fix.1.md
M docs/rules/520-JAVA_MAVEN_GRADLE.md
```
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/alpha.4.fix.1.md`, committer le correctif, puis préparer `0.0.2-alpha.5` consacré au profil Android.
### FAIL
Rester dans `0.0.2-alpha.4.fix.M`. Le correctif MUST rester limité à la cohérence de la tranche Java/Maven/Gradle.

162
deltas/0.0.2/alpha.4.md Normal file
View File

@@ -0,0 +1,162 @@
<!-- file: deltas/0.0.2/alpha.4.md -->
<!-- version: 1 -->
# Delta 0.0.2-alpha.4 — profil Java / Maven / Gradle
## Baseline
Version attendue avant application :
```text
0.0.2-alpha.3
```
Le history `history/0.0.2/alpha.3.md` MUST avoir été appliqué et committé avant ce delta.
Version après application :
```text
0.0.2-alpha.4
```
## Objet
Matérialiser le deuxième profil technologique de PGR : `Java / Maven / Gradle`.
Cette tranche conserve une frontière explicite entre :
```text
Java
→ règles du langage et de l'API
Maven / Gradle
→ spécialisations de build
Android / frameworks futurs
→ contraintes plus spécifiques qui pourront surcharger localement Java ou Gradle
```
Aucune règle Android, AGP, SDK, `minSdk`, `targetSdk`, `versionCode`, APK/AAB ou JNI n'est absorbée dans ce profil.
## Réconciliation retenue
Le profil reprend les principes déjà établis par PGR et les corpus de conception revus pour cette release :
- JDK LTS par défaut, dernière LTS compatible utilisée en priorité ;
- bascule vers une LTS plus ancienne lorsqu'une dépendance ou un outil l'exige ;
- non-LTS uniquement par exception justifiée ;
- séparation entre JDK de build et niveau Java/runtime supporté ;
- structure standard `src/main/java`, `src/main/resources`, `src/test/java`, `src/test/resources` ;
- packages orientés responsabilités et visibilité minimale ;
- imports explicites ;
- interfaces uniquement lorsqu'une vraie frontière existe ;
- pas de Lombok/convenience codegen implicite par défaut, sans interdire les annotations fonctionnelles de frameworks ;
- nullabilité et exceptions explicites ;
- tests unitaires/intégration/environnement séparables ;
- politique Maven centralisée dans le parent/root ;
- `dependencyManagement` / `pluginManagement` utilisés pour la politique commune sans ajouter artificiellement les dépendances aux modules ;
- Maven Wrapper conditionnel selon le besoin de reproductibilité ;
- configuration Gradle commune centralisée ;
- version catalog Gradle uniquement si la complexité le justifie ;
- contrainte Gradle exprimée comme minimum, range, pin exact ou latest compatible selon la vraie matrice ;
- Gradle Wrapper recommandé lorsqu'il apporte une reproductibilité réelle, sans interdire un Gradle système explicitement contraint ;
- un DSL Gradle cohérent par projet, sans transformer Groovy/Kotlin DSL en préférence de langage applicatif ;
- tâches ciblées pendant le développement, gates globales lorsque leur preuve devient utile ;
- `clean` traité comme maintenance ;
- outputs/caches/état local hors Git, avec wrappers comme exception volontaire lorsqu'ils sont retenus.
## Profil créé
Le nouveau propriétaire normatif est :
```text
docs/rules/520-JAVA_MAVEN_GRADLE.md
```
Il complète la famille `500 — languages / ecosystems` et n'introduit pas de nouvelle famille de navigation.
Aucun audit Java/Maven/Gradle n'est ajouté : le dépôt PGR ne contient actuellement aucun projet de ce type sur lequel une telle gate fournirait une preuve réelle.
## Scope
REPLACE :
```text
VERSION
RULES.md
docs/rules/000-README.md
```
ADD :
```text
docs/rules/520-JAVA_MAVEN_GRADLE.md
deltas/0.0.2/alpha.4.md
```
DELETE : aucun.
Aucun manifest de suppression n'est nécessaire.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2-alpha.4"
test -f docs/rules/520-JAVA_MAVEN_GRADLE.md
test -f deltas/0.0.2/alpha.4.md
grep -F 'le JDK de développement SHOULD être une version LTS' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'JDK utilisé pour construire' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'src/main/' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'Lombok et les outils équivalents de convenience/codegen implicite SHOULD NOT être utilisés par défaut' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'Le fichier PGR `VERSION` reste la version canonique de l' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'PGR MUST NOT ajouter un Maven Wrapper uniquement par cérémonie.' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'minimum seulement' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'Un Gradle Wrapper SHOULD être versionné lorsqu' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'Groovy DSL et Kotlin DSL sont tous deux reconnus.' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'gradle clean` est une opération de maintenance' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F 'Aucune commande Maven/Gradle n' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -F '520-JAVA_MAVEN_GRADLE.md' RULES.md
grep -F '520-JAVA_MAVEN_GRADLE.md' docs/rules/000-README.md
python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION RULES.md docs/rules/000-README.md docs/rules/520-JAVA_MAVEN_GRADLE.md deltas/0.0.2/alpha.4.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history est :
```text
M RULES.md
M VERSION
A deltas/0.0.2/alpha.4.md
M docs/rules/000-README.md
A docs/rules/520-JAVA_MAVEN_GRADLE.md
```
Revue opérateur complémentaire :
- confirmer que les règles Java restent distinctes des contraintes propres à Maven/Gradle ;
- confirmer que les contraintes Android restent hors de ce profil et pourront surcharger localement Gradle/JDK en `alpha.5` ;
- confirmer que la politique JDK privilégie les LTS sans pin exact arbitraire ;
- confirmer que Lombok/convenience codegen est distingué des annotations fonctionnelles de frameworks ;
- confirmer que Maven Wrapper et Gradle Wrapper sont des choix de reproductibilité justifiés, pas des obligations cérémonielles universelles ;
- confirmer qu'aucune commande Maven/Gradle réelle n'est exigée pour valider cette tranche documentaire dans le dépôt PGR lui-même.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/alpha.4.md`, committer la tranche, puis préparer `0.0.2-alpha.5` consacré au profil plateforme Android.
### FAIL
Rester dans `0.0.2-alpha.4.fix.M` tant que les frontières Java/build tool ou les politiques de compatibilité restent incorrectes. Effectuer un REPLAN si la tranche révèle une dérive significative du scope.

142
deltas/0.0.2/alpha.5.md Normal file
View File

@@ -0,0 +1,142 @@
<!-- file: deltas/0.0.2/alpha.5.md -->
<!-- version: 1 -->
# Delta 0.0.2-alpha.5 — profil plateforme Android
## Baseline
Version attendue avant application :
```text
0.0.2-alpha.4.fix.1
```
Le history `history/0.0.2/alpha.4.fix.1.md` MUST avoir été appliqué et committé avant ce delta.
Version après application :
```text
0.0.2-alpha.5
```
## Objet
Matérialiser le premier profil plateforme de PGR :
```text
docs/rules/610-ANDROID.md
```
La tranche consolide les règles Android réutilisables sans absorber les spécialisations Rust/JNI ou Tauri.
## Frontières retenues
Le profil Android possède notamment :
- la structure Android dans un dépôt mono- ou multi-plateforme ;
- Java comme défaut applicatif PGR lorsque rien n'impose un autre langage ;
- la matrice AGP / Gradle / JDK ;
- la séparation `compileSdk` / `targetSdk` / `minSdk` ;
- `VERSION` / `versionName` / `versionCode` ;
- configuration locale, signing et secrets ;
- modules et dépendances Android ;
- ABI lorsqu'un code natif existe, sans définir JNI ;
- niveaux de tests Android et ordre de validation ;
- manifest, permissions et ressources ;
- APK/AAB et packaging de distribution.
Restent hors scope :
```text
Rust / Android / JNI
Tauri desktop
Tauri mobile
Web / WASM
```
Ces compositions ne doivent pas être introduites implicitement dans `610-ANDROID.md`.
## Scope
REPLACE :
```text
VERSION
RULES.md
docs/rules/000-README.md
```
ADD :
```text
docs/rules/610-ANDROID.md
deltas/0.0.2/alpha.5.md
```
DELETE : aucun.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2-alpha.5"
test -f docs/rules/610-ANDROID.md
test -f deltas/0.0.2/alpha.5.md
grep -F 'Les profils Rust/JNI et Tauri ne sont pas définis ici.' docs/rules/610-ANDROID.md
grep -F 'Dans un dépôt multi-plateforme où une zone Android distincte est nécessaire' docs/rules/610-ANDROID.md
grep -F 'Java est le langage applicatif Android par défaut du profil PGR' docs/rules/610-ANDROID.md
grep -F 'Android Gradle Plugin' docs/rules/610-ANDROID.md
grep -F 'PGR MUST NOT déduire une hausse de `minSdk`' docs/rules/610-ANDROID.md
grep -F '`versionCode` est un compteur Android monotone distinct du SemVer.' docs/rules/610-ANDROID.md
grep -F '`local.properties` est un fichier local Android typique' docs/rules/610-ANDROID.md
grep -F 'Les secrets de signature ne sont jamais versionnés.' docs/rules/610-ANDROID.md
grep -F 'Une ABI annoncée comme supportée doit disposer d' docs/rules/610-ANDROID.md
grep -F 'JVM unit' docs/rules/610-ANDROID.md
grep -F '`AndroidManifest.xml` MUST déclarer uniquement les permissions' docs/rules/610-ANDROID.md
grep -F 'APK debug' docs/rules/610-ANDROID.md
grep -F 'PGR lui-même ne contient actuellement aucun projet Android' docs/rules/610-ANDROID.md
grep -F '610-ANDROID.md' RULES.md
grep -F '610-ANDROID.md' docs/rules/000-README.md
python3 -B scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
git diff --check
git add VERSION RULES.md docs/rules/000-README.md docs/rules/610-ANDROID.md deltas/0.0.2/alpha.5.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history est :
```text
M RULES.md
M VERSION
A deltas/0.0.2/alpha.5.md
M docs/rules/000-README.md
A docs/rules/610-ANDROID.md
```
Revue opérateur complémentaire :
- confirmer que le profil reste Android général et n'absorbe ni JNI ni Tauri ;
- confirmer que `compileSdk`, `targetSdk` et `minSdk` restent des contrats distincts ;
- confirmer que l'usage d'une toolchain moderne ne relève pas automatiquement `minSdk` ;
- confirmer que `versionCode` reste un compteur Android distinct de SemVer ;
- confirmer que les secrets et configurations locales restent hors Git ;
- confirmer que les niveaux de preuve unit/instrumented/smoke ne sont pas confondus ;
- confirmer qu'aucune validation Android réelle n'est revendiquée pour PGR lui-même en l'absence de projet Android.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/alpha.5.md`, committer la tranche, puis passer à `0.0.2-beta.1` pour la réconciliation des profils.
### FAIL
Rester dans `0.0.2-alpha.5.fix.M` jusqu'à correction. Un REPLAN n'est nécessaire que si la correction révèle un élargissement substantiel du scope.

View File

@@ -0,0 +1,91 @@
<!-- file: deltas/0.0.2/beta.1.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.2-beta.1.fix.1 — correction du quoting de la gate beta
## Baseline
Version attendue avant application :
```text
0.0.2-beta.1
```
Le history `history/0.0.2/beta.1.md` MUST avoir été appliqué et committé avant ce delta.
Version après application :
```text
0.0.2-beta.1.fix.1
```
## Objet
Corriger uniquement la commande Bash invalide observée dans la gate de `beta.1`.
La commande précédente utilisait une chaîne délimitée par apostrophes simples contenant elle-même l'apostrophe de `L'interdiction`, ce qui ouvrait une invite Bash de continuation.
Le document `docs/rules/610-ANDROID.md` est correct et n'est pas modifié.
La vérification est remplacée par une recherche littérale équivalente ne contenant aucune apostrophe conflictuelle :
```bash
grep -F 'reste possédée par `RULES.md`.' docs/rules/610-ANDROID.md
```
Aucune règle, aucun profil et aucun audit n'est ajouté ou modifié par ce fix.
## Scope
REPLACE :
```text
VERSION
```
ADD :
```text
deltas/0.0.2/beta.1.fix.1.md
```
DELETE : aucun.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2-beta.1.fix.1"
test -f deltas/0.0.2/beta.1.fix.1.md
grep -F 'reste possédée par `RULES.md`.' docs/rules/610-ANDROID.md
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 deltas/0.0.2/beta.1.fix.1.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history est exactement :
```text
M VERSION
A deltas/0.0.2/beta.1.fix.1.md
```
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/beta.1.fix.1.md`, committer le fix, puis préparer `0.0.2-rc.1`.
### FAIL
Rester dans `0.0.2-beta.1.fix.M`. Le scope du correctif MUST rester limité à la cohérence de la gate beta.

154
deltas/0.0.2/beta.1.md Normal file
View File

@@ -0,0 +1,154 @@
<!-- file: deltas/0.0.2/beta.1.md -->
<!-- version: 1 -->
# Delta 0.0.2-beta.1 — réconciliation des profils
## Baseline
Version attendue avant application :
```text
0.0.2-alpha.5
```
Le history `history/0.0.2/alpha.5.md` MUST avoir été appliqué et committé avant ce delta.
Version après application :
```text
0.0.2-beta.1
```
## Objet
Exécuter la réconciliation prévue après matérialisation des trois profils de `0.0.2` :
```text
510 — Rust / Cargo
520 — Java / Maven / Gradle
610 — Android
```
La tranche ne crée aucun nouveau profil technologique.
Elle vérifie et consolide l'ownership normatif, la composition général → langage/build → plateforme, l'absence de contradiction non résolue, la non-duplication des règles générales et la navigation documentaire.
## Résultat de la réconciliation
Aucune famille `700 — frameworks` ou `800 — architecture` n'est nécessaire pour fermer `0.0.2`.
Aucun profil composite n'est créé.
La composition actuellement démontrée reste :
```text
Rust ordinaire
→ GENERAL + 500 + 510
Java/Gradle Android
→ GENERAL + 500 + 520 + 600 + 610
```
Android peut raffiner les contraintes JDK/Gradle dans son scope lorsque la matrice AGP/Gradle/JDK l'exige. Cette spécialisation ne modifie pas le profil Java/Gradle hors Android.
Le profil Android est ajusté pour ne plus présenter l'interdiction générale des secrets comme une règle dont il serait propriétaire : `RULES.md` conserve l'ownership, tandis que `610-ANDROID.md` décrit les artefacts de signing Android qui tombent sous cette règle.
## Audit de navigation monotâche
La réconciliation doit vérifier réellement la navigation locale. PGR ajoute donc :
```text
scripts/audit_markdown_links.py
```
Cet audit est volontairement séparé de `audit_markdown_tables.py`.
Il contrôle uniquement l'existence des cibles de liens Markdown locaux inline. Il ne contrôle pas les anchors, les headers `file/version`, les responsabilités documentaires, les tableaux ou les URLs externes.
`PGR-NAV-001` devient l'owner de ce contrôle automatisé dans la matrice de validation.
`PGR-DOC-001` reste un contrôle de revue pour les headers, chemins et responsabilités documentaires, sans dupliquer la vérification des liens locaux.
## Scope
REPLACE :
```text
VERSION
docs/architecture/003-RULE_PROFILE_MODEL.md
docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
docs/rules/610-ANDROID.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
scripts/audit_markdown_links.py
deltas/0.0.2/beta.1.md
```
DELETE : aucun.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2-beta.1"
test -f scripts/audit_markdown_links.py
test -f deltas/0.0.2/beta.1.md
grep -F 'Aucune contradiction non résolue de même niveau' docs/architecture/003-RULE_PROFILE_MODEL.md
grep -F 'GENERAL + 500 + 520 + 600 + 610' docs/architecture/003-RULE_PROFILE_MODEL.md
grep -F 'Aucune famille `700` ou `800` n' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -F 'L'interdiction générale de versionner ou distribuer des secrets reste possédée par `RULES.md`.' docs/rules/610-ANDROID.md
grep -F '`PGR-NAV-001`' docs/validation/001-VALIDATION_MATRIX.md
grep -F 'audit_markdown_links.py' docs/validation/001-VALIDATION_MATRIX.md
grep -F 'plusieurs audits simples avec une responsabilité identifiable' docs/validation/001-VALIDATION_MATRIX.md
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/architecture/003-RULE_PROFILE_MODEL.md docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md docs/rules/610-ANDROID.md docs/validation/001-VALIDATION_MATRIX.md scripts/audit_markdown_links.py deltas/0.0.2/beta.1.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history est :
```text
M VERSION
A deltas/0.0.2/beta.1.md
M docs/architecture/003-RULE_PROFILE_MODEL.md
M docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
M docs/rules/610-ANDROID.md
M docs/validation/001-VALIDATION_MATRIX.md
A scripts/audit_markdown_links.py
```
## Revue opérateur complémentaire
- confirmer que beta n'introduit aucun profil technologique nouveau ;
- confirmer que `510`, `520` et `610` possèdent toujours des scopes distincts et compréhensibles ;
- confirmer qu'Android raffine Java/Gradle sans faire remonter ses contraintes vers tous les projets Java ;
- confirmer qu'aucun owner `700` ou `800` n'est créé sans contenu nécessaire ;
- confirmer que le nouvel audit reste strictement monotâche et read-only ;
- confirmer que la validation des liens locaux est désormais automatisée sans transformer `PGR-DOC-001` en wrapper multifonction.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/beta.1.md`, committer la tranche, puis préparer `0.0.2-rc.1`.
`rc.1` devra geler le scope, préparer l'entrée candidate `0.0.2` du changelog, finaliser le prompt manuel de reprise `0.0.3` et exécuter la gate documentaire complète.
### FAIL
Rester dans `0.0.2-beta.1.fix.M` jusqu'à correction. Aucun nouveau profil majeur ne doit être absorbé dans un fix beta.

120
deltas/0.0.2/rc.1.fix.1.md Normal file
View File

@@ -0,0 +1,120 @@
<!-- file: deltas/0.0.2/rc.1.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.2-rc.1.fix.1 — correction de l'audit inline des headers
## Baseline
Version attendue avant application :
```text
0.0.2-rc.1
```
Le history `history/0.0.2/rc.1.md` MUST avoir été appliqué et committé avant ce delta.
Version après application :
```text
0.0.2-rc.1.fix.1
```
## Objet
Corriger uniquement le script Python inline invalide observé dans la gate de `rc.1`.
La gate précédente matérialisait une chaîne Python sur deux lignes et produisait :
```text
SyntaxError: unterminated string literal
```
Le correctif n'ajoute pas de troisième audit PGR permanent : le scope RC reste gelé sur les audits `tables` et `liens locaux`.
L'audit ponctuel des headers est rejoué avec une forme sans échappement ambigu.
## Scope
REPLACE :
```text
VERSION
```
ADD :
```text
deltas/0.0.2/rc.1.fix.1.md
```
DELETE : aucun.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2-rc.1.fix.1"
test -f deltas/0.0.2/rc.1.fix.1.md
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
roots = [Path(name) for name in ('README.md', 'RULES.md', 'ROADMAP.md', 'CHANGELOG.md')]
for directory in ('docs', 'deltas', 'history', 'prompts'):
roots.extend(Path(directory).rglob('*.md'))
paths = sorted(set(roots))
errors = []
for path in paths:
lines = path.read_text(encoding='utf-8').splitlines()
expected = f'<!-- file: {path.as_posix()} -->'
if len(lines) < 2 or lines[0] != expected:
errors.append(f'{path}: invalid file header')
elif re.fullmatch(r'<!-- version: [1-9][0-9]* -->', lines[1]) is None:
errors.append(f'{path}: invalid version header')
if errors:
for error in errors:
print(error)
raise SystemExit(1)
print(f'Markdown header audit: clean ({len(paths)} file(s))')
PY
git diff --check
git add VERSION deltas/0.0.2/rc.1.fix.1.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history est exactement :
```text
M VERSION
A deltas/0.0.2/rc.1.fix.1.md
```
## Revue opérateur complémentaire
- confirmer que les deux audits PGR existants restent propres ;
- confirmer que l'audit ponctuel des headers s'exécute réellement et annonce un résultat `clean` ;
- confirmer qu'aucun contenu fonctionnel de `rc.1` n'est modifié ;
- confirmer que le scope RC reste gelé.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/rc.1.fix.1.md`, committer le fix, puis préparer la tranche stable `0.0.2` selon le workflow de release.
### FAIL
Rester dans `0.0.2-rc.1.fix.M`. À partir de `.fix.3`, appliquer la revue de plan/diagnostic imposée par la gouvernance.

158
deltas/0.0.2/rc.1.md Normal file
View File

@@ -0,0 +1,158 @@
<!-- file: deltas/0.0.2/rc.1.md -->
<!-- version: 1 -->
# Delta 0.0.2-rc.1 — gel des profils et préparation de release
## Baseline
Version attendue avant application :
```text
0.0.2-beta.1.fix.1
```
Le history `history/0.0.2/beta.1.fix.1.md` MUST avoir été appliqué et committé avant ce delta.
Version après application :
```text
0.0.2-rc.1
```
## Objet
Entrer en release candidate après réconciliation beta.
La tranche :
- gèle le scope `0.0.2` ;
- prépare l'entrée candidate stable `0.0.2` du changelog ;
- met à jour le plan avec l'état réellement observé de la beta et le freeze RC ;
- ajoute `prompts/003-V0_0_3_START_PROMPT.md` ;
- inclut dans ce prompt le texte manuel canonique de reprise et la règle de transmission du futur rapport `publish.001` ;
- exécute la gate documentaire complète applicable à PGR.
Aucun nouveau profil technologique, famille de règles ou audit n'est ajouté en RC.
## Scope gelé
Les owners technologiques de la release restent exactement :
```text
510 — Rust / Cargo
520 — Java / Maven / Gradle
610 — Android
```
Les audits PGR ajoutés pendant la release restent exactement :
```text
scripts/audit_markdown_tables.py
scripts/audit_markdown_links.py
```
Les profils différés restent différés.
## Scope
REPLACE :
```text
VERSION
CHANGELOG.md
docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
```
ADD :
```text
prompts/003-V0_0_3_START_PROMPT.md
deltas/0.0.2/rc.1.md
```
DELETE : aucun.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2-rc.1"
test -f prompts/003-V0_0_3_START_PROMPT.md
test -f deltas/0.0.2/rc.1.md
grep -F '## 0.0.2' CHANGELOG.md
grep -F '510 — Rust / Cargo' CHANGELOG.md
grep -F '520 — Java / Maven / Gradle' CHANGELOG.md
grep -F '610 — Android' CHANGELOG.md
grep -F 'Le scope RC est gelé' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -F 'beta.1.fix.1 PASS' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -F 'pgr-0.0.2-publish.001-report.md' prompts/003-V0_0_3_START_PROMPT.md
grep -F 'Prompt manuel de nouvelle session' prompts/003-V0_0_3_START_PROMPT.md
grep -F 'Partir de v0.0.2' prompts/003-V0_0_3_START_PROMPT.md
grep -F 'Ce texte doit être présenté spontanément' prompts/003-V0_0_3_START_PROMPT.md
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
roots = [Path(name) for name in ('README.md', 'RULES.md', 'ROADMAP.md', 'CHANGELOG.md')]
for directory in ('docs', 'deltas', 'history', 'prompts'):
roots.extend(Path(directory).rglob('*.md'))
errors = []
for path in sorted(set(roots)):
lines = path.read_text(encoding='utf-8').splitlines()
expected = f'<!-- file: {path.as_posix()} -->'
if len(lines) < 2 or lines[0] != expected:
errors.append(f'{path}: invalid file header')
elif re.fullmatch(r'<!-- version: [1-9][0-9]* -->', lines[1]) is None:
errors.append(f'{path}: invalid version header')
if errors:
raise SystemExit('
'.join(errors))
print(f'Markdown header audit: clean ({len(set(roots))} file(s))')
PY
git diff --check
git add VERSION CHANGELOG.md docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md prompts/003-V0_0_3_START_PROMPT.md deltas/0.0.2/rc.1.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history est exactement :
```text
M CHANGELOG.md
M VERSION
A deltas/0.0.2/rc.1.md
M docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
A prompts/003-V0_0_3_START_PROMPT.md
```
## Revue opérateur complémentaire
- confirmer qu'aucun nouveau profil n'est introduit en RC ;
- confirmer que le changelog décrit la release utilement sans recopier la chronologie des fixes ;
- confirmer que le prompt `0.0.3` impose une nouvelle vérification de l'archive taggée plutôt que de faire confiance au report précédent ;
- confirmer que le prompt manuel de nouvelle session est fourni spontanément et précise explicitement le report `publish.001` à joindre après publication ;
- confirmer que `0.0.3` reste centré sur templates initiaux et patterns d'audit, sans absorber les skeleton specifications de `0.0.4`.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/rc.1.md`, committer la RC, puis préparer la promotion stable `rel.001`.
### FAIL
Rester dans `0.0.2-rc.1.fix.M` jusqu'à correction. Aucun nouveau scope fonctionnel ne doit être introduit dans un fix RC.

154
deltas/0.0.2/rel.001.md Normal file
View File

@@ -0,0 +1,154 @@
<!-- file: deltas/0.0.2/rel.001.md -->
<!-- version: 1 -->
# Delta 0.0.2 rel.001 — promotion stable
## Baseline
Version attendue avant application :
```text
0.0.2-rc.1.fix.1
```
Le history `history/0.0.2/rc.1.fix.1.md` MUST avoir été appliqué et committé avant ce delta.
Version après application :
```text
0.0.2
```
`rel.001` est l'identifiant opérationnel de cette clôture stable ; il ne fait pas partie de la version SemVer produit.
## Objet
Promouvoir mécaniquement la release candidate validée vers la stable `0.0.2`, finaliser les métadonnées vivantes de la release et préparer le commit/tag stable.
Cette tranche n'introduit aucune nouvelle règle normative, aucun nouveau profil, aucun nouvel audit et aucun nouveau scope fonctionnel.
## Scope
REPLACE :
```text
VERSION
README.md
ROADMAP.md
docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
```
ADD :
```text
deltas/0.0.2/rel.001.md
```
DELETE : aucun.
## Changements
- `VERSION` devient `0.0.2` ;
- `README.md` présente `0.0.2` comme la première release matérialisant des profils technologiques réutilisables et référence son plan historique ;
- `ROADMAP.md` marque `0.0.2` terminé ;
- le plan `0.0.2` est clôturé après `rc.1.fix.1` et rappelle la séparation entre `rel.001` pré-tag et `publish.001` post-tag ;
- `CHANGELOG.md` n'est pas modifié : l'entrée stable `0.0.2` préparée en RC est déjà finalisée ;
- `prompts/003-V0_0_3_START_PROMPT.md` n'est pas modifié : il cible déjà `v0.0.2` et demande explicitement le rapport post-tag lorsqu'il existe.
## Validation opérateur
```bash
test "$(cat VERSION)" = "0.0.2"
grep -F 'La release `0.0.2` ajoute le premier modèle de profils réutilisables' README.md
grep -F 'plan historique des premiers profils `0.0.2`' README.md
grep -F -- '- `(x) 0.0.2`' ROADMAP.md
grep -F 'Plan clôturé par la promotion stable `0.0.2` après validation de `0.0.2-rc.1.fix.1`.' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -F 'Le contrôle post-tag `publish.001` reste une preuve séparée' docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
grep -Fx '## 0.0.2' CHANGELOG.md
test -f prompts/003-V0_0_3_START_PROMPT.md
grep -F 'v0.0.2' prompts/003-V0_0_3_START_PROMPT.md
grep -F 'pgr-0.0.2-publish.001-report.md' prompts/003-V0_0_3_START_PROMPT.md
for delta in deltas/0.0.2/*.md; do
name="${delta##*/}"
if [ "$name" = 'rel.001.md' ]; then
continue
fi
test -f "history/0.0.2/$name" || {
echo "Missing history for ${delta}" >&2
exit 1
}
done
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
roots = [Path(name) for name in ('README.md', 'RULES.md', 'ROADMAP.md', 'CHANGELOG.md')]
for directory in ('docs', 'deltas', 'history', 'prompts'):
roots.extend(Path(directory).rglob('*.md'))
paths = sorted(set(roots))
errors = []
for path in paths:
lines = path.read_text(encoding='utf-8').splitlines()
expected = f'<!-- file: {path.as_posix()} -->'
if len(lines) < 2 or lines[0] != expected:
errors.append(f'{path}: invalid file header')
elif re.fullmatch(r'<!-- version: [1-9][0-9]* -->', lines[1]) is None:
errors.append(f'{path}: invalid version header')
if errors:
for error in errors:
print(error)
raise SystemExit(1)
print(f'Markdown header audit: clean ({len(paths)} file(s))')
PY
git diff --check
git add VERSION README.md ROADMAP.md \
docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md \
deltas/0.0.2/rel.001.md
git diff --cached --check
git status --short
```
La sortie attendue avant ajout du history est exactement :
```text
M README.md
M ROADMAP.md
M VERSION
A deltas/0.0.2/rel.001.md
M docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md
```
## Revue opérateur complémentaire
- confirmer que la promotion stable ne contient aucun changement fonctionnel ou normatif nouveau ;
- confirmer que `0.0.2` clôt uniquement les profils `510`, `520` et `610` retenus par le plan ;
- confirmer que les profils différés restent différés ;
- confirmer que le prompt `0.0.3` demande explicitement l'archive taggée et le rapport `publish.001` lorsqu'il existe ;
- confirmer que `CHANGELOG.md` décrit la stable utilement sans recopier les détails de prerelease.
## Transition
### PASS
Créer et appliquer séparément `history/0.0.2/rel.001.md`, committer la stable `0.0.2`, créer le tag `v0.0.2`, pousser commit et tag, puis télécharger l'archive source produite depuis ce tag et exécuter la vérification post-tag `publish.001`.
### FAIL
Ne pas créer le tag. Corriger la promotion stable dans une nouvelle tranche de clôture explicite avant toute publication.

View File

@@ -0,0 +1,122 @@
<!-- file: deltas/0.0.3/alpha.1.fix.1.md -->
<!-- version: 1 -->
# Delta 0.0.3-alpha.1.fix.1 — périmètre Rust/Cargo du plan
## Baseline et version
Baseline : tranche `0.0.3-alpha.1` validée par l'opérateur, avec `history/0.0.3/alpha.1.md` appliqué et committé. Ce fix ne doit pas être appliqué sur un état où le history `alpha.1` n'est pas encore dans le commit de base.
Version avant application :
```text
0.0.3-alpha.1
```
Version après application :
```text
0.0.3-alpha.1.fix.1
```
## Motif et observations
Le delta `alpha.1` a passé sa gate mécanique. La revue du plan ensuite a montré que la tranche Rust prévue autour du seul `rustfmt.toml` n'intégrait pas les réglages Clippy et les deux manifests Cargo communs déjà décrits dans `510-RUST_CARGO.md` et pratiqués dans KSP et Games.
Les archives de référence supplémentaires inspectées sont :
```text
khadhroony-solana-project-v0.3.16.zip SHA-256 db3cc1b3fc3fb07ee864b02e2a7346c673d4cf63b33e8e872aca6c6458856ca0
games-v0.3.5.zip SHA-256 5f5fdee1a271386766d059657d6eaa831acdc263b3e722fed738808335c0a105
```
Les deux projets centralisent lints et métadonnées Cargo, et conservent `rustfmt.toml` ainsi qu'un `clippy.toml`. Les scripts Rust des projets mêlent plusieurs politiques ; le plan corrigé en tire des candidats de propriétés isolées sans les recopier. La seule exception de lints locaux constatée parmi les `45` crates inspectées concerne la frontière Android de Games.
## Scope
REPLACE :
```text
VERSION
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
```
ADD :
```text
deltas/0.0.3/alpha.1.fix.1.md
```
DELETE : aucun.
Le plan passe de `<!-- version: 1 -->` à `<!-- version: 2 -->` pour sa révision réelle. Les snapshots `deltas/0.0.3/alpha.1.md` et `history/0.0.3/alpha.1.md` restent inchangés. Aucun template, script, règle normative ou manifest de suppression n'est ajouté dans ce fix.
## Contenu corrigé
- le template Rust prévu couvre `rustfmt.toml`, les niveaux de lint Rust/Clippy dans Cargo, les manifests workspace/membre et, seulement si justifié, des paramètres distincts dans `clippy.toml` ;
- le plan compare les deux corpus réels, relève l'héritage explicite des lints et son exception Android bornée, distingue les options communes des seuils ou dépendances propres à un projet ;
- les tranches sont redimensionnées : `alpha.2` formatage/Clippy, `alpha.3` manifests Cargo, `alpha.4` audit de headers Markdown, puis décision conditionnelle sur un template de workflow ;
- les scripts Rust KSP/Games servent de corpus de comparaison pour des audits futurs read-only et monotâches, sans transfert direct de leurs règles locales vers PGR.
## Validation opérateur
Après application sur le commit `alpha.1` :
```bash
test "$(cat VERSION)" = '0.0.3-alpha.1.fix.1'
git cat-file -e HEAD:history/0.0.3/alpha.1.md
test -f deltas/0.0.3/alpha.1.fix.1.md
test -f history/0.0.3/alpha.1.md
test ! -e history/0.0.3/alpha.1.fix.1.md
grep -Fx '<!-- version: 2 -->' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -F 'Les `22` crates KSP héritent des lints workspace' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -F '### alpha.2 — formatage et configuration Clippy' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -F '### alpha.3 — manifests Cargo workspace et crate membre' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -F '### alpha.4 — audit de headers Markdown' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
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
files = [Path(name) for name in ('README.md', 'RULES.md', 'ROADMAP.md', 'CHANGELOG.md')]
for directory in ('docs', 'deltas', 'history', 'prompts'):
files.extend(Path(directory).rglob('*.md'))
files = sorted(set(files))
for path in files:
lines = path.read_text(encoding='utf-8').splitlines()
assert len(lines) >= 2 and lines[0] == f'<!-- file: {path.as_posix()} -->', path
assert re.fullmatch(r'<!-- version: [1-9][0-9]* -->', lines[1]), path
print(f'Markdown header audit: clean ({len(files)} file(s))')
PY
git diff --check
git add VERSION docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md deltas/0.0.3/alpha.1.fix.1.md
git diff --cached --check
git status --short
```
Avant ajout du history du fix, le scope indexé attendu est :
```text
M VERSION
A deltas/0.0.3/alpha.1.fix.1.md
M docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
```
Revue complémentaire : confirmer que la correction ne copie pas de version de dépendance, de path Cargo ou de seuil Clippy arbitraire ; vérifier que le plan reste une prévision et que `alpha.1` demeure un snapshot historique inchangé.
## Transition
### PASS
Produire et appliquer séparément `history/0.0.3/alpha.1.fix.1.md` avec les résultats réellement observés, puis committer ce fix avant tout delta `alpha.2`.
### FAIL
Consigner le résultat réel dans le history du fix et poursuivre par `alpha.1.fix.2` limité au cadrage, ou engager un REPLAN explicite si le scope Rust doit changer davantage.

101
deltas/0.0.3/alpha.1.md Normal file
View File

@@ -0,0 +1,101 @@
<!-- file: deltas/0.0.3/alpha.1.md -->
<!-- version: 1 -->
# Delta 0.0.3-alpha.1 — audit de baseline et cadrage
## Baseline
Archive fournie `pgr-v0.0.2.zip`, déclarée téléchargée du tag Gitea `v0.0.2`, vérifiée avec SHA-256 :
```text
8dc5c979a4d722b4ef6ec84b6227c8cbfffb3f865f4ea9063c03ecb1e365cdc4
```
Le rapport post-tag externe `pgr-0.0.2-publish.001-report.md` indique `PASS` et le même hash. Il n'est pas ajouté rétroactivement à la stable. Aucun `.git` n'est attendu dans l'archive source.
Version avant application : `0.0.2`.
Version après application : `0.0.3-alpha.1`.
## Objet
Exécuter le cadrage demandé par `prompts/003-V0_0_3_START_PROMPT.md` : audit complet de la stable, vérification des règles et de la chaîne historique, inventaire des sujets utiles, choix d'un scope initial et découpage proportionné dans un plan actif.
Le résultat détaillé de l'audit, ses limites et les décisions de scope sont consignés dans `docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md`. L'archive est cohérente dans les contrôles réalisés ; aucune correction rétroactive de `0.0.2` n'est nécessaire avant cette tranche.
## Scope
REPLACE :
```text
VERSION
```
ADD :
```text
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
deltas/0.0.3/alpha.1.md
```
DELETE : aucun.
L'archive delta contient exactement les fichiers complets ci-dessus, avec les mêmes chemins relatifs. Aucun manifest de suppression, history, nouveau template ou script d'audit n'appartient à cette tranche.
Les index et les documents historiques restent conformes sans mise à jour cérémonielle : la roadmap annonce déjà `0.0.3`, le changelog conserve les releases stables et les index documentaires pointent vers les collections existantes.
## Validation opérateur
Appliquer l'archive delta à la copie de travail du dépôt fondée sur `v0.0.2`. Depuis sa racine :
```bash
test "$(cat VERSION)" = '0.0.3-alpha.1'
test -f docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
test -f deltas/0.0.3/alpha.1.md
test ! -e history/0.0.3/alpha.1.md
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
files = [Path(name) for name in ('README.md', 'RULES.md', 'ROADMAP.md', 'CHANGELOG.md')]
for directory in ('docs', 'deltas', 'history', 'prompts'):
files.extend(Path(directory).rglob('*.md'))
files = sorted(set(files))
for path in files:
lines = path.read_text(encoding='utf-8').splitlines()
assert len(lines) >= 2 and lines[0] == f'<!-- file: {path.as_posix()} -->', path
assert re.fullmatch(r'<!-- version: [1-9][0-9]* -->', lines[1]), path
print(f'Markdown header audit: clean ({len(files)} file(s))')
PY
git diff --check
git add VERSION docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md deltas/0.0.3/alpha.1.md
git diff --cached --check
git status --short
```
Avant d'ajouter le history, le scope attendu des fichiers indexés est :
```text
M VERSION
A docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
A deltas/0.0.3/alpha.1.md
```
L'opérateur confirme également que la baseline provient bien du tag déclaré, que le hash concorde avec la preuve post-tag, que les `24` couples historiques antérieurs sont conservés, que les profils différés ne sont pas matérialisés, et que le plan ne fait pas passer une prévision pour une règle déjà active.
## Transition
### PASS
Rédiger et livrer séparément `history/0.0.3/alpha.1.md` avec les résultats réellement observés ; l'appliquer et committer la tranche. Préparer seulement ensuite `0.0.3-alpha.2`.
### FAIL
Enregistrer le résultat réellement observé dans le history de `alpha.1`, puis corriger le cadrage dans `0.0.3-alpha.1.fix.1` ou produire un REPLAN motivé. Aucune implémentation `alpha.2` ne doit être absorbée dans le fix.

123
deltas/0.0.3/alpha.2.md Normal file
View File

@@ -0,0 +1,123 @@
<!-- file: deltas/0.0.3/alpha.2.md -->
<!-- version: 1 -->
# Delta 0.0.3-alpha.2 — outillage Rust/Cargo partagé
## Baseline et version
Baseline : `0.0.3-alpha.1.fix.1` avec `history/0.0.3/alpha.1.fix.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.0.3-alpha.1.fix.1
```
Version après application :
```text
0.0.3-alpha.2
```
## Objet
Matérialiser trois configurations Rust/Cargo directement issues des pratiques éprouvées dans KSP et Games, avec des instructions explicites d'adaptation. L'opérateur a précisé après le gate de `alpha.1.fix.1` que la sortie Cargo est généralement déportée vers `../builds/<projet>/target/` et que Rustfmt/Clippy constituent des conventions de départ qu'il réutilise avec des adaptations mineures.
Le `clippy.toml` livré conserve les réglages communs utiles aux deux corpus, sans copier leurs listes d'identifiants propres ni leurs entrées vides. Les niveaux des lints appartiendront aux templates `Cargo.toml` de `alpha.3`, conformément au profil `510`.
## Scope
REPLACE :
```text
VERSION
docs/000-README.md
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
```
ADD :
```text
templates/rust-cargo/rustfmt.toml
templates/rust-cargo/clippy.toml
templates/rust-cargo/.cargo/config.toml
docs/templates/001-RUST_CARGO_TOOLING.md
deltas/0.0.3/alpha.2.md
```
DELETE : aucun.
Les fichiers complets sont livrés dans l'archive delta. Aucun history `alpha.2`, manifest de suppression, crate PGR ou script d'audit nouveau n'y est inclus.
## Validation opérateur
Depuis la racine du dépôt après application du delta :
```bash
test "$(cat VERSION)" = '0.0.3-alpha.2'
git cat-file -e HEAD:history/0.0.3/alpha.1.fix.1.md
test ! -e history/0.0.3/alpha.2.md
python3 -B - <<'PY'
from pathlib import Path
import tomllib
root = Path('templates/rust-cargo')
rustfmt = tomllib.loads((root / 'rustfmt.toml').read_text(encoding='utf-8'))
clippy = tomllib.loads((root / 'clippy.toml').read_text(encoding='utf-8'))
cargo = tomllib.loads((root / '.cargo/config.toml').read_text(encoding='utf-8'))
assert rustfmt['edition'] == '2024'
assert rustfmt['max_width'] == 160
assert clippy['allow-unwrap-in-tests'] is True
assert clippy['allowed-idents-below-min-chars'] == ['id']
assert cargo['build']['target-dir'] == '../builds/project-name/target'
assert cargo['build']['build-dir'] == cargo['build']['target-dir']
for path in (root / 'rustfmt.toml', root / 'clippy.toml', root / '.cargo/config.toml'):
lines = path.read_text(encoding='utf-8').splitlines()
assert lines[0] == f'# file: {path.as_posix()}', path
assert lines[1] == '# version: 1', path
print('Rust/Cargo template TOML audit: clean (3 file(s))')
PY
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
files = [Path(name) for name in ('README.md', 'RULES.md', 'ROADMAP.md', 'CHANGELOG.md')]
for directory in ('docs', 'deltas', 'history', 'prompts'):
files.extend(Path(directory).rglob('*.md'))
files = sorted(set(files))
for path in files:
lines = path.read_text(encoding='utf-8').splitlines()
assert len(lines) >= 2 and lines[0] == f'<!-- file: {path.as_posix()} -->', path
assert re.fullmatch(r'<!-- version: [1-9][0-9]* -->', lines[1]), path
print(f'Markdown header audit: clean ({len(files)} file(s))')
PY
git diff --check
git add VERSION docs/000-README.md docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md \
docs/templates/001-RUST_CARGO_TOOLING.md deltas/0.0.3/alpha.2.md \
templates/rust-cargo/rustfmt.toml templates/rust-cargo/clippy.toml \
templates/rust-cargo/.cargo/config.toml
git diff --cached --check
git status --short
```
Scope attendu avant ajout du history : les trois `REPLACE` et les cinq `ADD` énumérés ci-dessus, sans modification des deltas ou histories précédents.
Revue opérateur : confirmer que la convention de sortie Cargo vers un dossier frère est expliquée avec son chemin relatif réel, que `project-name` est à remplacer avant copie et que les lints de niveau Cargo et les manifests restent bien au scope de `alpha.3`. La gate de cette tranche reste documentaire/TOML : PGR ne contient aucun workspace Rust à compiler.
## Transition
### PASS
Produire séparément `history/0.0.3/alpha.2.md` avec les sorties réellement observées, l'appliquer et committer avant de préparer `alpha.3` consacré aux manifests Cargo.
### FAIL
Enregistrer la défaillance réelle puis corriger ces seuls templates ou instructions dans `alpha.2.fix.1`, sauf besoin de REPLAN justifié.

118
deltas/0.0.3/alpha.3.md Normal file
View File

@@ -0,0 +1,118 @@
<!-- file: deltas/0.0.3/alpha.3.md -->
<!-- version: 1 -->
# Delta 0.0.3-alpha.3 — audits de style Rust ciblés
## Baseline et version
Baseline : `0.0.3-alpha.2`, avec `history/0.0.3/alpha.2.md` appliqué et committé. Ce delta MUST NOT être appliqué tant que ce commit n'existe pas.
Version avant application :
```text
0.0.3-alpha.2
```
Version après application :
```text
0.0.3-alpha.3
```
## Objet et REPLAN
Après la gate PASS de `alpha.2`, l'opérateur a signalé les audits Python de style Rust de KSP et Games et demandé leur découpage en scripts plus petits et monotâches. L'examen de leurs `audit_rust_general_rules.py` montre qu'ils combinent blancs, constantes, ordre de modules, headers, rustdoc et règles de façade. Résultat REPLAN : `SPLIT`. Les deux contrôles de style apportant une preuve autonome passent à `alpha.3` ; les manifests Cargo initialement prévus ici passent à `alpha.4`, l'audit des headers Markdown à `alpha.5` et la décision workflow à `alpha.6`.
Ajouter un contrôle facultatif d'espacement des lignes vides et un contrôle facultatif des blocs de constantes racine, avec un helper lexical commun sans politique autonome. Le profil `510` possède leurs conventions optionnelles, la documentation de validation explicite leur adoption et leurs limites ; la matrice répertorie leur test ciblé. Rustfmt reste propriétaire du tri interne qu'il effectue déjà ; Clippy garde ses lints. Aucun script KSP/Games complet ni gate Rust obligatoire n'est copié dans PGR.
## Scope
REPLACE :
```text
VERSION
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
docs/rules/510-RUST_CARGO.md
docs/templates/001-RUST_CARGO_TOOLING.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
docs/validation/002-RUST_STYLE_AUDITS.md
scripts/_rust_audit_common.py
scripts/audit_rust_blank_lines.py
scripts/audit_rust_const_blocks.py
tests/test_rust_audits.py
deltas/0.0.3/alpha.3.md
```
DELETE : aucun.
Les fichiers complets figurent dans l'archive delta. Aucun history `alpha.3`, changement rétroactif de delta/history, manifest Cargo, suppression ou modification des corpus de référence n'est inclus.
## Limites et prévalidation
Les audits sont read-only, sélectionnent explicitement des fichiers `.rs` et signalent les violations avec chemin et ligne. La prévalidation hors dépôt PGR a porté sur `300` sources KSP et `59` sources Games : l'audit des blancs est propre sur les deux ; l'audit des constantes est propre sur Games mais affiche `17` signaux KSP lorsqu'il est lancé globalement. Des séquences KSP portent un ordre métier ou de schéma ; l'ordre alphabétique ne leur est pas imposé. La sélection du projet doit donc exclure les fichiers ayant une sémantique d'ordre incompatible. Les scripts ne parsèrent pas intégralement Rust et ne remplacent ni Rustfmt ni Clippy.
Cette prévalidation de corpus n'est pas une validation opérateur de la tranche. Le dépôt PGR ne contient ni crate Rust ni fichiers Rust sujets à un audit produit. Les cas de test Python du delta vérifient les contrats réellement livrés, y compris échecs attendus et statut CLI.
## Validation opérateur
Après application sur le commit `alpha.2` :
```bash
test "$(cat VERSION)" = '0.0.3-alpha.3'
git cat-file -e HEAD:history/0.0.3/alpha.2.md
test -f history/0.0.3/alpha.2.md
test -f deltas/0.0.3/alpha.3.md
test ! -e history/0.0.3/alpha.3.md
grep -Fx '<!-- version: 4 -->' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -F '### alpha.4 — manifests Cargo workspace et crate membre' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -F '### alpha.5 — audit de headers Markdown' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
python3 -B -m unittest discover -s tests -p test_rust_audits.py -v
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
files = [Path(name) for name in ('README.md', 'RULES.md', 'ROADMAP.md', 'CHANGELOG.md')]
for directory in ('docs', 'deltas', 'history', 'prompts'):
files.extend(Path(directory).rglob('*.md'))
files = sorted(set(files))
for path in files:
lines = path.read_text(encoding='utf-8').splitlines()
assert len(lines) >= 2 and lines[0] == f'<!-- file: {path.as_posix()} -->', path
assert re.fullmatch(r'<!-- version: [1-9][0-9]* -->', lines[1]), path
print(f'Markdown header audit: clean ({len(files)} file(s))')
PY
git diff --check
git add VERSION docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md \
docs/rules/510-RUST_CARGO.md docs/templates/001-RUST_CARGO_TOOLING.md \
docs/validation/001-VALIDATION_MATRIX.md docs/validation/002-RUST_STYLE_AUDITS.md \
scripts/_rust_audit_common.py scripts/audit_rust_blank_lines.py \
scripts/audit_rust_const_blocks.py tests/test_rust_audits.py \
deltas/0.0.3/alpha.3.md
git diff --cached --check
git status --short
```
Scope attendu avant ajout du history : cinq `REPLACE` et six `ADD` exactement comme ci-dessus. Revue opérateur : vérifier le rôle facultatif des deux scripts, leur dépendance commune, la sélection des fichiers Rust et la priorité de l'ordre sémantique ; confirmer que les manifests Cargo restent prévus en `alpha.4`.
## Transition
### PASS
Produire séparément `history/0.0.3/alpha.3.md` avec les résultats réellement exécutés, l'appliquer et committer cette tranche avant tout delta `alpha.4`.
### FAIL
Consigner le diagnostic dans le history `alpha.3`, puis corriger ce scope dans `alpha.3.fix.1` ou engager un nouveau REPLAN si la séparation des contrôles n'est plus adaptée.

191
deltas/0.0.3/alpha.4.md Normal file
View File

@@ -0,0 +1,191 @@
<!-- file: deltas/0.0.3/alpha.4.md -->
<!-- version: 1 -->
# Delta 0.0.3-alpha.4 — manifests Cargo workspace et membre
## Baseline et version
Baseline : `0.0.3-alpha.3`, avec `history/0.0.3/alpha.3.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.0.3-alpha.3
```
Version après application :
```text
0.0.3-alpha.4
```
## Objet
Fournir les deux manifests Cargo prévus dans le plan après son REPLAN `SPLIT` : un workspace virtuel à release commune et une crate bibliothèque membre. Les sections d'héritage, les lints Rust/Clippy communs, la version de release et le périmètre des dépendances doivent être compréhensibles sans figer les identités KSP/Games ni une liste de dépendances tierces.
Le manifest racine reprend les trois lints Rust et les `18` niveaux Clippy effectivement communs aux deux projets. Il déclare un bloc `[workspace.dependencies]` initialement vide. Le membre hérite explicitement des métadonnées présentes et des lints par `[lints] workspace = true`. La documentation distingue l'adaptation ordinaire d'une exception FFI locale, qui ne peut combiner cet héritage avec des lints locaux dans une même crate. La version `0.1.0` et le nom `project-core-lib` sont des exemples à remplacer, pas des valeurs de PGR ou d'un projet tiers.
Le plan vivant reçoit deux corrections factuelles : PGR possède désormais plus de deux utilitaires Python et la famille énumère cinq responsabilités, et non quatre. Ces corrections n'altèrent aucun delta ni history précédent.
## Scope
REPLACE :
```text
VERSION
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
docs/templates/001-RUST_CARGO_TOOLING.md
```
ADD :
```text
templates/rust-cargo/Cargo.toml
templates/rust-cargo/crates/project-core-lib/Cargo.toml
docs/templates/002-CARGO_MANIFESTS.md
deltas/0.0.3/alpha.4.md
```
DELETE : aucun.
L'archive contient uniquement ces fichiers complets. Aucun fichier source Rust, history `alpha.4`, suppression, dépendance de build de PGR ou version tierce n'est introduit.
## Validation opérateur
Après application sur le commit `alpha.3` :
```bash
test "$(cat VERSION)" = '0.0.3-alpha.4'
git cat-file -e HEAD:history/0.0.3/alpha.3.md
test -f history/0.0.3/alpha.3.md
test ! -e history/0.0.3/alpha.4.md
test -f deltas/0.0.3/alpha.4.md
python3 -B - <<'PY'
from pathlib import Path
import json
import shutil
import subprocess
import tempfile
import tomllib
source = Path('templates/rust-cargo')
root_file = source / 'Cargo.toml'
member_file = source / 'crates/project-core-lib/Cargo.toml'
root = tomllib.loads(root_file.read_text(encoding='utf-8'))
member = tomllib.loads(member_file.read_text(encoding='utf-8'))
assert root['workspace']['resolver'] == '3'
assert root['workspace']['members'] == ['crates/project-core-lib']
assert root['workspace']['package']['version'] == '0.1.0' # Explicit example.
assert root['workspace']['package']['edition'] == '2024'
assert root['workspace']['package']['publish'] is False
assert root['workspace']['dependencies'] == {}
assert root['workspace']['lints']['rust'] == {
'missing_docs': 'warn', 'unreachable_pub': 'deny', 'unsafe_code': 'forbid'
}
clippy = root['workspace']['lints']['clippy']
assert len(clippy) == 18 and clippy['implicit_return'] == 'deny'
assert clippy['needless_return'] == 'allow' and clippy['unwrap_used'] == 'deny'
assert member['package']['name'] == 'project-core-lib'
for field in ('version', 'edition', 'publish'):
assert member['package'][field] == {'workspace': True}, field
assert member['dependencies'] == {} and member['lints'] == {'workspace': True}
for path in (root_file, member_file):
lines = path.read_text(encoding='utf-8').splitlines()
assert lines[:2] == [f'# file: {path.as_posix()}', '# version: 1'], path
print('Cargo manifest TOML audit: clean (2 file(s))')
if shutil.which('cargo') is None:
print('Cargo workspace smoke: toolchain unavailable; TOML audit only')
else:
with tempfile.TemporaryDirectory(prefix='pgr-cargo-manifests-') as folder:
workspace = Path(folder)
crate = workspace / 'crates/project-core-lib'
(crate / 'src').mkdir(parents=True)
shutil.copy2(root_file, workspace / 'Cargo.toml')
shutil.copy2(member_file, crate / 'Cargo.toml')
(crate / 'src/lib.rs').write_text(
'//! Minimal template check.\n\n/// Return one.\n'
'pub fn value() -> u8 {\n return 1;\n}\n', encoding='utf-8'
)
command = ['cargo', 'metadata', '--manifest-path', str(workspace / 'Cargo.toml'),
'--format-version', '1', '--no-deps', '--offline']
result = subprocess.run(command, cwd=workspace, text=True,
capture_output=True, check=True)
package = json.loads(result.stdout)['packages'][0]
assert package['name'] == 'project-core-lib'
assert package['version'] == '0.1.0' and package['edition'] == '2024'
subprocess.run(['cargo', 'check', '--workspace', '--offline'],
cwd=workspace, check=True)
if subprocess.run(['cargo', 'clippy', '--version'], capture_output=True).returncode == 0:
subprocess.run(['cargo', 'clippy', '--workspace', '--all-targets',
'--all-features', '--offline', '--', '-D', 'warnings'],
cwd=workspace, check=True)
# Inherited forbid must reject unsafe code before a local FFI exception.
(crate / 'src/lib.rs').write_text(
'//! Minimal FFI exception check.\n\n/// Return one.\n'
'pub fn value() -> u8 {\n'
' let value: u8 = 1;\n let ptr: *const u8 = &value;\n'
' unsafe { return *ptr; }\n}\n', encoding='utf-8'
)
rejected = subprocess.run(['cargo', 'check', '--workspace', '--offline'],
cwd=workspace, capture_output=True, text=True)
assert rejected.returncode != 0 and 'unsafe' in rejected.stderr
# Cargo must accept a local lint table in place of inheritance.
local = member_file.read_text(encoding='utf-8').replace(
'[lints]\nworkspace = true\n',
'[lints.rust]\nmissing_docs = "warn"\n'
'unreachable_pub = "deny"\nunsafe_code = "allow"\n\n'
'[lints.clippy]\n' + ''.join(
f'{name} = {json.dumps(level)}\n' for name, level in clippy.items()
)
)
assert '[lints.rust]' in local and '[lints]\nworkspace = true' not in local
(crate / 'Cargo.toml').write_text(local, encoding='utf-8')
subprocess.run(['cargo', 'check', '--workspace', '--offline'],
cwd=workspace, check=True)
print('Cargo workspace smoke: clean (inherited and local lints)')
PY
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
files = [Path(name) for name in ('README.md', 'RULES.md', 'ROADMAP.md', 'CHANGELOG.md')]
for directory in ('docs', 'deltas', 'history', 'prompts'):
files.extend(Path(directory).rglob('*.md'))
files = sorted(set(files))
for path in files:
lines = path.read_text(encoding='utf-8').splitlines()
assert len(lines) >= 2 and lines[0] == f'<!-- file: {path.as_posix()} -->', path
assert re.fullmatch(r'<!-- version: [1-9][0-9]* -->', lines[1]), path
print(f'Markdown header audit: clean ({len(files)} file(s))')
PY
git diff --check
git add VERSION docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md \
docs/templates/001-RUST_CARGO_TOOLING.md docs/templates/002-CARGO_MANIFESTS.md \
templates/rust-cargo/Cargo.toml templates/rust-cargo/crates/project-core-lib/Cargo.toml \
deltas/0.0.3/alpha.4.md
git diff --cached --check
git status --short
```
Scope attendu avant ajout du history : les trois `REPLACE` et les quatre `ADD` ci-dessus. Revue opérateur : vérifier que le manifest membre hérite seulement des champs racine présents, que les lints Clippy sont ceux des deux corpus et que la version d'exemple ainsi que le nom de crate doivent être remplacés lors d'une adoption réelle. Si Cargo n'est pas disponible dans l'environnement de PGR, le smoke workspace est indiqué comme non exécuté et le parsing TOML reste la preuve locale ; l'adoption dans un projet Rust doit exécuter sa propre gate Cargo.
## Transition
### PASS
Fournir séparément `history/0.0.3/alpha.4.md` avec les sorties réellement observées, l'appliquer et committer la tranche avant le delta `alpha.5` relatif aux headers Markdown.
### FAIL
Consigner le défaut dans le history, puis corriger manifests ou instructions dans `alpha.4.fix.1` sauf besoin justifié d'un nouveau REPLAN.

90
deltas/0.0.3/alpha.5.md Normal file
View File

@@ -0,0 +1,90 @@
<!-- file: deltas/0.0.3/alpha.5.md -->
<!-- version: 1 -->
# Delta 0.0.3-alpha.5 — audit des headers Markdown
## Baseline et version
Baseline : `0.0.3-alpha.4`, avec `history/0.0.3/alpha.4.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.0.3-alpha.4
```
Version après application :
```text
0.0.3-alpha.5
```
## Objet
Extraire le contrôle des headers Markdown répété en Python inline dans les gates précédentes. `scripts/audit_markdown_headers.py` vérifie une seule propriété documentaire : les deux premières lignes de chaque fichier choisi doivent déclarer son chemin relatif canonique et une révision interne positive. Le script accepte des chemins explicites depuis la racine du projet, lit sans modifier, produit des erreurs déterministes avec chemin et ligne et distingue violation de sélection invalide.
`docs/rules/300-DOCUMENTATION.md` possède la convention pour le corpus Markdown de PGR. La matrice inscrit l'audit mécanique séparément de la revue des rôles documentaires, de l'audit des tableaux et de celui des liens. Une révision positive ne démontre pas qu'elle a été incrémentée à bon escient : cela reste une décision de revue.
## Scope
REPLACE :
```text
VERSION
docs/rules/300-DOCUMENTATION.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
scripts/audit_markdown_headers.py
tests/test_markdown_headers.py
deltas/0.0.3/alpha.5.md
```
DELETE : aucun.
L'archive livre uniquement ces fichiers complets. Aucun history `alpha.5`, réécriture historique, nouveau profil de langage ou autre audit Markdown n'est inclus.
## Validation opérateur
Après application sur le commit `alpha.4`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.3-alpha.5'
git cat-file -e HEAD:history/0.0.3/alpha.4.md
test -f history/0.0.3/alpha.4.md
test -f deltas/0.0.3/alpha.5.md
test ! -e history/0.0.3/alpha.5.md
grep -Fx '<!-- version: 2 -->' docs/rules/300-DOCUMENTATION.md
grep -Fx '<!-- version: 8 -->' docs/validation/001-VALIDATION_MATRIX.md
python3 -B -m unittest discover -s tests -p test_markdown_headers.py -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/rules/300-DOCUMENTATION.md \
docs/validation/001-VALIDATION_MATRIX.md scripts/audit_markdown_headers.py \
tests/test_markdown_headers.py deltas/0.0.3/alpha.5.md
git diff --cached --check
git status --short
```
Scope attendu avant ajout du history : trois `REPLACE` et trois `ADD`, sans toucher à un delta ou history antérieur. Vérifier que le nouveau script reste monotâche, traite les headers faux et les chemins absents, et ne remplace ni la revue des documents ni les deux autres audits Markdown.
## Transition
### PASS
Produire séparément `history/0.0.3/alpha.5.md` avec les preuves réellement observées, l'appliquer et committer avant la tranche `alpha.6`, consacrée à la décision conditionnelle sur le template de workflow.
### FAIL
Enregistrer la défaillance et corriger ce scope dans `alpha.5.fix.1`, sauf REPLAN explicitement justifié.

92
deltas/0.0.3/alpha.6.md Normal file
View File

@@ -0,0 +1,92 @@
<!-- file: deltas/0.0.3/alpha.6.md -->
<!-- version: 1 -->
# Delta 0.0.3-alpha.6 — prompt manuel de reprise
## Baseline et version
Baseline : `0.0.3-alpha.5`, avec `history/0.0.3/alpha.5.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.0.3-alpha.5
```
Version après application :
```text
0.0.3-alpha.6
```
## Décision et objet
La comparaison des prompts `002` et `003` et des règles `210-WORKFLOW.md` confirme une répétition utile : baseline taggée, version cible, première tranche et consigne d'audit à la reprise. `003` ajoute une preuve de vérification post-tag distincte et une phrase manuelle à remettre à l'opérateur. La décision conditionnelle de la tranche est donc **retenir** une spécification courte dans `docs/templates/003-NEW_SESSION_PROMPT.md`.
Ce document rassemble les champs à renseigner et une forme de message manuel, avec une branche claire lorsque le rapport post-tag manque ou n'est pas `PASS`. Il ne génère rien, ne fige aucun nom de projet ni preuve et ne prépare pas encore le prompt versionné de `0.0.4`. `docs/rules/210-WORKFLOW.md` reste propriétaire de la séquence delta/history/commit et de la publication après tag ; le plan vivant enregistre la décision.
## Scope
REPLACE :
```text
VERSION
docs/rules/210-WORKFLOW.md
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
```
ADD :
```text
docs/templates/003-NEW_SESSION_PROMPT.md
deltas/0.0.3/alpha.6.md
```
DELETE : aucun.
L'archive contient uniquement ces fichiers complets. Aucun history `alpha.6`, prompt `004`, générateur, modification de prompts historiques ou changement de configuration Rust/Cargo n'est inclus.
## Validation opérateur
Après application sur le commit `alpha.5`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.3-alpha.6'
git cat-file -e HEAD:history/0.0.3/alpha.5.md
test -f history/0.0.3/alpha.5.md
test -f deltas/0.0.3/alpha.6.md
test -f docs/templates/003-NEW_SESSION_PROMPT.md
test ! -e history/0.0.3/alpha.6.md
test ! -e prompts/004-V0_0_4_START_PROMPT.md
grep -Fx '<!-- version: 3 -->' docs/rules/210-WORKFLOW.md
grep -Fx '<!-- version: 6 -->' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -F '### Retenu : spécification courte du prompt manuel de nouvelle session' \
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
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/rules/210-WORKFLOW.md \
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md \
docs/templates/003-NEW_SESSION_PROMPT.md deltas/0.0.3/alpha.6.md
git diff --cached --check
git status --short
```
Scope attendu avant ajout du history : trois `REPLACE` et deux `ADD`. Revue opérateur : confirmer que le message manuel est actionnable sans supposer un rapport `PASS`, que son contrat versionné est distinct, que les prompts `002`/`003` restent historiques et que la préparation de `0.0.4` n'est pas anticipée.
## Transition
### PASS
Produire séparément `history/0.0.3/alpha.6.md` d'après la gate exécutée, l'appliquer et committer avant de passer à `beta.1` pour la réconciliation de release.
### FAIL
Enregistrer le diagnostic puis corriger uniquement cette spécification et ses renvois dans `alpha.6.fix.1`, sauf REPLAN justifié.

115
deltas/0.0.3/beta.1.md Normal file
View File

@@ -0,0 +1,115 @@
<!-- file: deltas/0.0.3/beta.1.md -->
<!-- version: 1 -->
# Delta 0.0.3-beta.1 — réconciliation documentaire
## Baseline et version
Baseline : `0.0.3-alpha.6`, avec `history/0.0.3/alpha.6.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.0.3-alpha.6
```
Version après application :
```text
0.0.3-beta.1
```
## Objet et résultat de la revue
Réconcilier la navigation, les propriétaires et les contrôles après les six tranches alpha et le fix documentaire. Les sept deltas `alpha.1` à `alpha.6`, fix inclus, ont chacun un history `PASS` fourni par la gate opérateur ; leur chaîne de versions est continue depuis `0.0.2`. La règle `210` possède le workflow ; la règle `300` possède les headers Markdown ; le profil `510` possède les conventions Rust facultatives. Les documents `docs/templates/` expliquent comment adapter les cinq fichiers Rust/Cargo et le message de reprise, tandis que les scripts restent de petits contrôles de propriétés délimitées.
La revue relève quatre corrections de documents vivants : exposer le plan actif depuis `README.md`, ouvrir la navigation directe depuis `docs/000-README.md` et décrire son template de workflow, actualiser dans le plan l'audit des headers déjà livré, et rendre dans la matrice l'audit des liens applicable à une tranche alpha qui modifie la navigation. La réconciliation n'ajoute aucune famille normative, audit, règle de version universelle, dépendance de build ou prompt `0.0.4`. Les versions et seuils du modèle Cargo restent des exemples ou choix adaptables, et les snapshots antérieurs restent intacts.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
deltas/0.0.3/beta.1.md
```
DELETE : aucun.
L'archive contient exactement ces fichiers complets. Le history de `alpha.6` est livré séparément, celui de `beta.1` n'existe pas encore ; `CHANGELOG.md`, les règles, templates techniques, scripts, tests et prompts ne sont pas modifiés.
## Validation opérateur
Après application de `history/0.0.3/alpha.6.md` et son commit, appliquer ce delta puis exécuter à la racine :
```bash
test "$(cat VERSION)" = '0.0.3-beta.1'
git cat-file -e HEAD:history/0.0.3/alpha.6.md
test -f history/0.0.3/alpha.6.md
test -f deltas/0.0.3/beta.1.md
test ! -e history/0.0.3/beta.1.md
test ! -e prompts/004-V0_0_4_START_PROMPT.md
grep -Fx '<!-- version: 5 -->' README.md
grep -Fx '<!-- version: 3 -->' docs/000-README.md
grep -Fx '<!-- version: 7 -->' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -Fx '<!-- version: 9 -->' docs/validation/001-VALIDATION_MATRIX.md
python3 -B -m unittest discover -s tests -p 'test_*.py' -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
tranches = ['alpha.1', 'alpha.1.fix.1', 'alpha.2', 'alpha.3',
'alpha.4', 'alpha.5', 'alpha.6']
version = '0.0.2'
for name in tranches:
delta = Path(f'deltas/0.0.3/{name}.md').read_text(encoding='utf-8')
history = Path(f'history/0.0.3/{name}.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history), name
assert f'Version avant application : `{version}`.' in delta or \
f'Version avant application :\n\n```text\n{version}\n```' in delta, name
version = f'0.0.3-{name}'
assert f'Version après application : `{version}`.' in delta or \
f'Version après application :\n\n```text\n{version}\n```' in delta, name
for path in sorted(Path('templates/rust-cargo').rglob('*.toml')):
tomllib.loads(path.read_text(encoding='utf-8'))
print(f'Reconciliation audit: clean ({len(tranches)} PASS histories, 5 TOML files)')
PY
git diff --check
git add VERSION README.md docs/000-README.md \
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md \
docs/validation/001-VALIDATION_MATRIX.md deltas/0.0.3/beta.1.md
git diff --cached --check
git status --short
```
Scope attendu avant ajout du history : cinq `REPLACE` et un `ADD` exactement comme ci-dessus. Revue opérateur : confirmer que les liens pointent vers les documents propriétaires et que les valeurs du template Cargo restent des exemples adaptables ; les gates alpha déjà observées ne sont pas réinterprétées et la RC n'est pas déclarée acquise par cette prévalidation.
## Transition
### PASS
Produire séparément `history/0.0.3/beta.1.md` avec les résultats réellement observés, l'appliquer et committer `beta.1` avant de préparer `rc.1`.
### FAIL
Enregistrer le diagnostic dans le history de `beta.1`, puis corriger la réconciliation dans `beta.1.fix.1` ou faire un REPLAN explicite si le scope a changé.

117
deltas/0.0.3/rc.1.md Normal file
View File

@@ -0,0 +1,117 @@
<!-- file: deltas/0.0.3/rc.1.md -->
<!-- version: 1 -->
# Delta 0.0.3-rc.1 — gel du scope et préparation de release
## Baseline et version
Baseline : `0.0.3-beta.1`, avec `history/0.0.3/beta.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.0.3-beta.1
```
Version après application :
```text
0.0.3-rc.1
```
## Objet et gel
La gate de `beta.1` est `PASS`. La RC gèle le scope fonctionnel : cinq modèles Rust/Cargo adaptables, deux audits facultatifs de style Rust, un audit de headers Markdown et une spécification du message manuel de reprise. La candidate `0.0.3` du changelog décrit ces résultats sans détailler les fixes ; le plan enregistre le gel et l'état observé de beta.
Le prompt `004` prépare le cadrage de `0.0.4` consacré aux skeleton specifications Markdown et à la composition des profils/templates. Il demande un audit de la future archive taggée `v0.0.3` et traite son rapport post-tag comme une preuve conditionnelle, jamais acquise en RC. Son message manuel doit être ajusté et remis après la publication et son contrôle réel. Aucun skeleton complet, générateur, règle normative nouvelle, audit nouveau ni projet source modifié n'appartient à `rc.1`.
## Scope
REPLACE :
```text
VERSION
CHANGELOG.md
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
```
ADD :
```text
prompts/004-V0_0_4_START_PROMPT.md
deltas/0.0.3/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. Les histories et deltas antérieurs, les règles, modèles techniques, scripts, tests et `ROADMAP.md` restent inchangés.
## Gate opérateur de release candidate
Après application sur le commit `beta.1`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.0.3-rc.1'
git cat-file -e HEAD:history/0.0.3/beta.1.md
test -f history/0.0.3/beta.1.md
test -f deltas/0.0.3/rc.1.md
test -f prompts/004-V0_0_4_START_PROMPT.md
test ! -e history/0.0.3/rc.1.md
grep -Fx '<!-- version: 4 -->' CHANGELOG.md
grep -Fx '## 0.0.3 (candidate)' CHANGELOG.md
grep -Fx '<!-- version: 8 -->' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -F 'La gate opérateur de `beta.1` est `PASS`' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -F 'pgr-0.0.3-publish.001-report.md' prompts/004-V0_0_4_START_PROMPT.md
grep -F "Si le rapport manque ou n'est pas PASS" prompts/004-V0_0_4_START_PROMPT.md
python3 -B -m unittest discover -s tests -p 'test_*.py' -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
names = ['alpha.1', 'alpha.1.fix.1', 'alpha.2', 'alpha.3',
'alpha.4', 'alpha.5', 'alpha.6', 'beta.1']
version = '0.0.2'
for name in names:
delta = Path(f'deltas/0.0.3/{name}.md').read_text(encoding='utf-8')
history = Path(f'history/0.0.3/{name}.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history), name
assert f'Version avant application : `{version}`.' in delta or \
f'Version avant application :\n\n```text\n{version}\n```' in delta, name
version = f'0.0.3-{name}'
assert f'Version après application : `{version}`.' in delta or \
f'Version après application :\n\n```text\n{version}\n```' in delta, name
assert {p.stem for p in Path('deltas/0.0.3').glob('*.md')} - \
{p.stem for p in Path('history/0.0.3').glob('*.md')} == {'rc.1'}
for path in Path('templates/rust-cargo').rglob('*.toml'):
tomllib.loads(path.read_text(encoding='utf-8'))
print(f'RC integration audit: clean ({len(names)} PASS histories, 5 TOML files)')
PY
git diff --check
git add VERSION CHANGELOG.md docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md \
prompts/004-V0_0_4_START_PROMPT.md deltas/0.0.3/rc.1.md
git diff --cached --check
git status --short
```
Scope attendu avant ajout du history : trois `REPLACE` et deux `ADD`. Revue opérateur : contrôler que le changelog décrit la release et non les tranches, que les exemples Cargo restent adaptables, que `004` concerne exclusivement la future `0.0.4` et que sa preuve post-tag n'est pas présumée. Une gate RC PASS n'est pas un tag ni une vérification de l'archive publiée.
## Transition
### PASS
Produire séparément `history/0.0.3/rc.1.md` d'après la gate observée, l'appliquer puis committer la RC avant la promotion stable `rel.001`.
### FAIL
Consigner les échecs dans le history RC et corriger le scope gelé dans `rc.1.fix.1` ; réviser le plan si un changement fonctionnel plus large s'impose.

116
deltas/0.0.3/rel.001.md Normal file
View File

@@ -0,0 +1,116 @@
<!-- file: deltas/0.0.3/rel.001.md -->
<!-- version: 1 -->
# Delta 0.0.3 rel.001 — promotion stable pré-tag
## Baseline et version
Baseline : `0.0.3-rc.1`, avec `history/0.0.3/rc.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.0.3-rc.1
```
Version après application :
```text
0.0.3
```
`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.3`. La tranche finalise la présentation de la release, marque la roadmap terminée, retire la mention « candidate » du changelog et clôt le plan comme référence historique. Le prompt `004`, les règles, les modèles, les audits et les tests sont ceux validés en RC : aucune fonctionnalité, règle ou preuve post-tag nouvelle n'est introduite.
La validation de cette tranche est **pré-tag**. Ni le tag `v0.0.3` ni une archive téléchargée depuis Gitea ni un rapport `publish.001` ne sont déclarés existants par ce delta. Ils suivent le history PASS, le commit stable et la publication du tag.
## Scope
REPLACE :
```text
VERSION
README.md
ROADMAP.md
CHANGELOG.md
docs/000-README.md
docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
```
ADD :
```text
deltas/0.0.3/rel.001.md
```
DELETE : aucun.
L'archive contient uniquement ces fichiers complets. `history/0.0.3/rc.1.md` arrive séparément ; le history de `rel.001` sera rédigé après sa gate. Le rapport post-tag sera hors de 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.3'
git cat-file -e HEAD:history/0.0.3/rc.1.md
test -f history/0.0.3/rc.1.md
test -f deltas/0.0.3/rel.001.md
test -f prompts/004-V0_0_4_START_PROMPT.md
test ! -e history/0.0.3/rel.001.md
grep -Fx '<!-- version: 6 -->' README.md
grep -Fx '<!-- version: 4 -->' ROADMAP.md
grep -Fx '<!-- version: 5 -->' CHANGELOG.md
grep -Fx '<!-- version: 4 -->' docs/000-README.md
grep -Fx '<!-- version: 9 -->' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -F 'La release `0.0.3` fournit les premiers modèles Rust/Cargo' README.md
grep -F 'plan historique des templates et audits `0.0.3`' README.md
grep -F -- '- `(x) 0.0.3`' ROADMAP.md
grep -Fx '## 0.0.3' CHANGELOG.md
grep -F 'La gate opérateur de `rc.1` est `PASS`' docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
grep -F "La vérification de l'archive" docs/plans/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md
python3 -B - <<'PY'
from pathlib import Path
import re
names = ['alpha.1', 'alpha.1.fix.1', 'alpha.2', 'alpha.3',
'alpha.4', 'alpha.5', 'alpha.6', 'beta.1', 'rc.1']
for name in names:
history = Path(f'history/0.0.3/{name}.md')
assert Path(f'deltas/0.0.3/{name}.md').is_file(), name
assert re.search(r'## Statut\s+PASS\s', history.read_text(encoding='utf-8')), name
assert {p.stem for p in Path('deltas/0.0.3').glob('*.md')} - \
{p.stem for p in Path('history/0.0.3').glob('*.md')} == {'rel.001'}
print(f'Stable history audit: clean ({len(names)} PASS histories, 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/003-V0_0_3_TEMPLATES_AUDITS_PLAN.md deltas/0.0.3/rel.001.md
git diff --cached --check
git status --short
```
Scope attendu avant ajout du history : six `REPLACE` et un `ADD` exactement comme ci-dessus. Revue opérateur : confirmer que le scope RC ne change pas, que la présentation du dépôt, le changelog et la roadmap décrivent la même stable, que le prompt `004` reste conditionnel au rapport post-tag et que les snapshots historiques restent intacts. Les `15` tests et les cinq TOML validés en RC restent des preuves utilisables parce qu'aucun code, script, test ou template n'a changé dans cette promotion.
## Transition
### PASS
Rédiger et livrer séparément `history/0.0.3/rel.001.md` avec le résultat réellement observé ; l'appliquer et committer la stable. Ensuite seulement, créer et publier le tag canonique `v0.0.3`, télécharger son archive source depuis Gitea, vérifier cette archive et conserver séparément la preuve post-tag `publish.001`. Le texte manuel du prompt `004` n'est remis à l'opérateur qu'après vérification de l'archive et d'un rapport post-tag PASS réel.
### FAIL
Consigner le diagnostic dans le history de `rel.001`, ne pas tagger, puis corriger la clôture dans une tranche explicite avant publication.

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.

235
deltas/0.1.2/alpha.1.md Normal file
View File

@@ -0,0 +1,235 @@
<!-- file: deltas/0.1.2/alpha.1.md -->
<!-- version: 1 -->
# Delta 0.1.2-alpha.1 — audit de stable et cadrage Java / Gradle
## Baseline et sources
Baseline PGR autoritaire : archive source téléchargée depuis le tag Gitea `v0.1.1`, accompagnée du rapport externe `pgr-0.1.1-publish.001-report.md` avec statut `PASS`.
SHA-256 vérifiés sur les fichiers réellement fournis :
```text
pgr-v0.1.1(1).zip caaf8f456f7f8520172ea7705fd0cf5c5bf0e942dc4a773410bcbe7fe4ce243a
pgr-0.1.1-publish.001-report(1).md 3eafc2767225526a6cba65b3b62a45a664b71a1f2fa049915ec243a196e14bb3
games-v0.3.6(1).zip ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8
```
Les archives locales PGR et Games comportent `(1)` dans leur nom, mais leurs empreintes correspondent exactement aux baselines canoniques `pgr-v0.1.1.zip` et `games-v0.3.6.zip` attendues par le rapport/prompt.
Version avant application :
```text
0.1.1
```
Version après application :
```text
0.1.2-alpha.1
```
## Objet
Exécuter `prompts/008-V0_1_2_START_PROMPT.md` : vérifier intégralement la stable `v0.1.1` et son rapport post-tag, auditer le corpus Games autoritaire sur Java/Gradle et ses preuves historiques, relire `520-JAVA_MAVEN_GRADLE.md`, `610-ANDROID.md` et la revue d'horizon, puis créer le plan `0.1.2` avant toute normalisation importante.
`alpha.1` reste un gate de cadrage. Aucune règle Java/Gradle, règle Android, validation spécialisée, template, skeleton ou audit nouveau n'est encore créé ou modifié.
## Résultat de l'audit d'intake
La stable PGR et son rapport post-tag concordent : SHA-256 attendu, CRC propre, racine unique `pgr/`, `256` fichiers, `36` répertoires en comptant la racine, aucun symlink, absence normale de `.git` et `VERSION=0.1.1`.
Les quatre modules de tests Python ont été rejoués par groupes et donnent `48/48 PASS`. Les audits Markdown sont propres : `231` fichiers pour les headers, `9` tables sur `231` fichiers et `267` liens locaux sur `231` fichiers. Les cinq templates TOML Rust/Cargo sont parsables.
Les `83` couples delta/history de `0.0.1` à `0.1.1` sont complets. La vérité `0.1.1` conserve `alpha.2 FAIL`, `alpha.2.fix.1 PASS`, `alpha.3.fix.1 FAIL`, `alpha.3.fix.2 PASS`, puis `rel.1 PASS`.
Le corpus Games fourni possède exactement le SHA canonique attendu, `502` fichiers et aucun symlink. Ses audits statiques principaux sont propres. Il exerce quatre sources Java canoniques sous `src/main/java/` et un projet Gradle multi-module en Groovy DSL avec ownership identifiable entre `settings.gradle`, root build, `gradle.properties`, modules et scripts Gradle communs.
Les histories Games montrent successivement une preuve avec Wrapper Gradle `9.6.0` + JDK 17, puis la décision durable et validée d'utiliser Gradle système `>= 9.6.0` avec le JDK courant. Les gates suivantes ont utilisé Temurin `25.0.4.1 LTS` et Gradle `9.7.1`, tandis que la glue Java restait explicitement source/target `17`. Cette trajectoire confirme la séparation build JDK / niveau Java et le caractère conditionnel du Wrapper sans généraliser les versions exactes.
Games n'exerce ni Maven, ni version catalog, ni tests Java génériques suffisants pour créer de nouveaux artefacts correspondants. Aucun `pom.xml`, Maven Wrapper, Gradle Wrapper ou `libs.versions.toml` n'est présent dans la stable `0.3.6`.
Les contraintes AGP, SDK/NDK, ABI/JNI, SDL3, manifests, APK/AAB, signing, AVD/devices et smokes restent explicitement hors scope : elles appartiennent à Android ou au produit Games et sont réservées à `0.1.3` pour la réévaluation PGR Android.
Le plan classe les choix observés avec `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER` et retient une révision ciblée de `520` plutôt qu'une copie de Games ou une multiplication d'artefacts.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
```
ADD :
```text
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
deltas/0.1.2/alpha.1.md
```
DELETE : aucun.
`RULES.md`, `ROADMAP.md`, `CHANGELOG.md`, `docs/rules/520-JAVA_MAVEN_GRADLE.md`, `docs/rules/610-ANDROID.md`, les autres règles, templates, skeletons, validations, scripts, studies, prompts et histories existants restent inchangés dans `alpha.1`.
Aucun `history/0.1.2/alpha.1.md` n'est anticipé avant la gate opérateur.
## Validation opérateur
Après application sur la stable `0.1.1`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.1.2-alpha.1'
test -f docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
test -f deltas/0.1.2/alpha.1.md
test ! -e history/0.1.2/alpha.1.md
grep -Fx '<!-- version: 20 -->' README.md
grep -Fx '<!-- version: 32 -->' docs/000-README.md
grep -F '008-V0_1_2_JAVA_GRADLE_REEVALUATION_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,
'0.1.1': 11,
}
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.1').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.fix.1.md'] == 'FAIL'
assert statuses['alpha.3.fix.2.md'] == 'PASS'
assert statuses['rel.1.md'] == 'PASS'
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
assert '- `(x) 0.1.1`' in roadmap
for release in range(2, 8):
assert f'- `( ) 0.1.{release}`' in roadmap, release
assert '0.1.8' not in roadmap
assert 'skeleton Tauri jusqu\'au réexamen 0.1.4' in roadmap
prompt = Path('prompts/008-V0_1_2_START_PROMPT.md').read_text(encoding='utf-8')
for phrase in (
'Version cible : `0.1.2`',
'Première tranche attendue : `0.1.2-alpha.1`',
'ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8',
'ADOPT / KEEP-LOCAL / OVERRIDE / DEFER',
'Gradle système versus Wrapper',
'Le profil `520` possède également Maven.',
'`0.1.2` MUST NOT absorber les responsabilités',
):
assert phrase in prompt, phrase
profile = Path('docs/rules/520-JAVA_MAVEN_GRADLE.md').read_text(encoding='utf-8')
for phrase in (
'JDK utilisé pour construire',
'PGR MUST NOT ajouter un Maven Wrapper uniquement par cérémonie.',
'Un Gradle Wrapper SHOULD être versionné lorsqu\'il apporte une reproductibilité utile',
'Groovy DSL et Kotlin DSL sont tous deux reconnus.',
'`gradle clean` est une opération de maintenance',
):
assert phrase in profile, phrase
android = Path('docs/rules/610-ANDROID.md').read_text(encoding='utf-8')
for phrase in (
'Matrice AGP / Gradle / JDK',
'`compileSdk`, `targetSdk` et `minSdk`',
'ABI et code natif',
'Signing et secrets',
):
assert phrase in android, phrase
plan = Path('docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'Classification initiale des décisions Games',
'`ADOPT`',
'`KEEP-LOCAL`',
'`OVERRIDE`',
'`DEFER`',
'alpha.2 — révision ciblée Java / Gradle',
'beta.1 — réconciliation et décision d\'artefacts',
'AGP 9.4.0',
'Aucun skeleton Java/Gradle ni artefact Maven nouveau n\'est prévu par défaut.',
'0.1.3 — réévaluation pratique du profil Android à partir de Games',
):
assert phrase in plan, phrase
assert Path('docs/rules/520-JAVA_MAVEN_GRADLE.md').read_text(encoding='utf-8').startswith(
'<!-- file: docs/rules/520-JAVA_MAVEN_GRADLE.md -->\n<!-- version: 2 -->'
)
assert Path('docs/rules/610-ANDROID.md').read_text(encoding='utf-8').startswith(
'<!-- file: docs/rules/610-ANDROID.md -->\n<!-- version: 2 -->'
)
print('0.1.2 alpha.1 structural audit: clean (83 prior pairs, Games classified, Android 0.1.3 boundary preserved)')
PY
git diff --check
git add VERSION README.md docs/000-README.md \
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md \
deltas/0.1.2/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.2/alpha.1.md
M docs/000-README.md
A docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
```
La revue opérateur doit également confirmer que :
- `alpha.1` n'a pas modifié `520-JAVA_MAVEN_GRADLE.md` avant validation du cadrage ;
- `610-ANDROID.md` reste intact et aucune responsabilité Android n'a été absorbée dans le plan Java/Gradle ;
- les versions exactes Games (`Gradle 9.6/9.7.1`, JDK 25, Java 17, AGP 9.4.0) restent des preuves ou choix locaux, pas des contraintes PGR universelles ;
- l'absence de Wrapper dans Games est classée comme choix local compatible avec une politique PGR conditionnelle, pas comme interdiction globale du Wrapper ;
- aucun nouveau template/audit/skeleton Maven ou Gradle n'est créé sans preuve supplémentaire ;
- Games reste un corpus externe non modifié et son adoption reste réservée à `0.1.5` ;
- le skeleton Tauri reste `DEFER` jusqu'à `0.1.4` ;
- aucun nouveau numéro au-delà de `0.1.7` n'est réservé.
## Transition
### PASS
Produire `history/0.1.2/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.2-alpha.2` consacré à la révision normative ciblée de `520-JAVA_MAVEN_GRADLE.md`, sans modification de `610-ANDROID.md` et sans nouvel artefact Maven.
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.2-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 la révision normative prévue pour `alpha.2`.

View File

@@ -0,0 +1,213 @@
<!-- file: deltas/0.1.2/alpha.2.fix.1.md -->
<!-- version: 1 -->
# Delta 0.1.2-alpha.2.fix.1 — récupération de contamination inter-projet
## Baseline et diagnostic
Baseline Git observée et déjà publiée sur `origin/master` :
```text
17b7ef23a18c913f986c7d57caf958d33479363d
```
Le commit précédent observé est :
```text
6e978bfed8c1ad10d1888cd3da92aeaf70338b7e
```
La gate opérateur de `0.1.2-alpha.2` avait été exécutée avec succès avant cette chaîne de commits : tests Python, audits Markdown, gate Java/Gradle et contrôles de scope étaient `PASS`. `history/0.1.2/alpha.2.md` conserve donc ce résultat réel.
La publication de la tranche a ensuite été contaminée par des fichiers provenant d'un autre projet. Les preuves Git montrent notamment :
- `6e978bf` porte les vraies modifications PGR de `alpha.2`, mais ajoute aussi `history/0.0.1/alpha.3.fix.1.md` et utilise un message de commit étranger ;
- `17b7ef2` ajoute `Cargo.toml`, `crates/knowledge-domain-lib/src/content_family.rs` et `deltas/0.0.1/alpha.3.fix.2.md` ;
- `17b7ef2` remplace `docs/plans/001-V0_0_1_FOUNDATION_PLAN.md` et `docs/validation/001-VALIDATION_MATRIX.md` par du contenu Knowledge ;
- `git diff --check 17b7ef2^ 17b7ef2` signale en plus une ligne vide finale parasite dans la matrice de validation ;
- les commits étant déjà poussés, le présent fix restaure l'état PGR par un nouveau commit et ne réécrit pas l'historique distant.
Version avant correction au niveau Git publié : état contaminé après `0.1.2-alpha.2`.
Version après application :
```text
0.1.2-alpha.2.fix.1
```
## Objet
Ramener la branche publiée à l'état PGR attendu après `alpha.2`, tout en préservant les vraies modifications Java/Maven/Gradle et leur history `PASS`.
Ce fix est exclusivement un correctif de provenance et d'hygiène Git. Il ne change aucune décision normative de `alpha.2` et n'absorbe ni le REPLAN Java/Maven/Gradle préparé pour la tranche suivante ni le scope Android réservé à `0.1.3`.
## Scope
REPLACE :
```text
VERSION
docs/plans/001-V0_0_1_FOUNDATION_PLAN.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
deltas/0.1.2/alpha.2.fix.1.md
manifests/0.1.2/alpha.2.fix.1.delete.txt
```
DELETE :
```text
Cargo.toml
crates/knowledge-domain-lib/src/content_family.rs
deltas/0.0.1/alpha.3.fix.2.md
history/0.0.1/alpha.3.fix.1.md
```
Le manifest de suppression doit contenir exactement ces quatre chemins.
Les fichiers suivants de `alpha.2` MUST rester inchangés par le fix :
```text
deltas/0.1.2/alpha.2.md
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
docs/rules/520-JAVA_MAVEN_GRADLE.md
history/0.1.2/alpha.2.md
```
`docs/rules/610-ANDROID.md` reste également inchangé.
## Restauration autoritaire
`docs/plans/001-V0_0_1_FOUNDATION_PLAN.md` et `docs/validation/001-VALIDATION_MATRIX.md` n'étaient modifiés ni par `alpha.1` ni par `alpha.2`. Leur contenu attendu est donc exactement celui de la stable `v0.1.1`.
Le fix restaure ces deux fichiers depuis cette baseline au lieu de tenter de corriger manuellement le contenu Knowledge injecté.
## Application du manifest
Après extraction du delta, appliquer explicitement le manifest de suppression :
```bash
while IFS= read -r path; do
case "$path" in
''|'#'*) continue ;;
esac
rm -f -- "$path"
done < manifests/0.1.2/alpha.2.fix.1.delete.txt
```
Les éventuels répertoires devenus vides ne sont pas des chemins suivis par Git et n'affectent pas le contenu publié.
## Validation opérateur
Le stash `pgr-0.1.2-alpha.3-before-alpha.2-recovery` doit rester intact pendant toute cette gate. Ne pas exécuter `stash pop` avant fermeture du fix.
```bash
test "$(git rev-parse HEAD)" = '17b7ef23a18c913f986c7d57caf958d33479363d'
test "$(git rev-parse origin/master)" = '17b7ef23a18c913f986c7d57caf958d33479363d'
test "$(cat VERSION)" = '0.1.2-alpha.2.fix.1'
test -f history/0.1.2/alpha.2.md
grep -A2 '^## Statut$' history/0.1.2/alpha.2.md | grep -Fx 'PASS'
test -f deltas/0.1.2/alpha.2.fix.1.md
test ! -e history/0.1.2/alpha.2.fix.1.md
test ! -e Cargo.toml
test ! -e crates/knowledge-domain-lib/src/content_family.rs
test ! -e deltas/0.0.1/alpha.3.fix.2.md
test ! -e history/0.0.1/alpha.3.fix.1.md
git diff --exit-code v0.1.1 -- \
docs/plans/001-V0_0_1_FOUNDATION_PLAN.md \
docs/validation/001-VALIDATION_MATRIX.md
grep -Fx '<!-- version: 2 -->' docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
grep -Fx '<!-- version: 3 -->' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -Fx '<!-- version: 2 -->' docs/rules/610-ANDROID.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
manifest = Path('manifests/0.1.2/alpha.2.fix.1.delete.txt')
paths = [line.strip() for line in manifest.read_text(encoding='utf-8').splitlines() if line.strip() and not line.lstrip().startswith('#')]
expected = [
'Cargo.toml',
'crates/knowledge-domain-lib/src/content_family.rs',
'deltas/0.0.1/alpha.3.fix.2.md',
'history/0.0.1/alpha.3.fix.1.md',
]
assert paths == expected, (paths, expected)
for path in expected:
assert not Path(path).exists(), path
history = Path('history/0.1.2/alpha.2.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
alpha2 = Path('deltas/0.1.2/alpha.2.md').read_text(encoding='utf-8')
assert '# Delta 0.1.2-alpha.2 — révision ciblée Java / Gradle' in alpha2
plan = Path('docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
assert plan.startswith('<!-- file: docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md -->\n<!-- version: 2 -->')
profile = Path('docs/rules/520-JAVA_MAVEN_GRADLE.md').read_text(encoding='utf-8')
assert profile.startswith('<!-- file: docs/rules/520-JAVA_MAVEN_GRADLE.md -->\n<!-- version: 3 -->')
android = Path('docs/rules/610-ANDROID.md').read_text(encoding='utf-8')
assert android.startswith('<!-- file: docs/rules/610-ANDROID.md -->\n<!-- version: 2 -->')
for forbidden in (
'knowledge-domain-lib',
'# Matrice de validation Knowledge',
'knowledge-pgr-server',
):
assert forbidden not in Path('docs/validation/001-VALIDATION_MATRIX.md').read_text(encoding='utf-8'), forbidden
print('0.1.2 alpha.2.fix.1 recovery audit: clean (foreign Knowledge paths removed, PGR baseline restored, alpha.2 preserved)')
PYGATE
git diff --check
git add -A
git diff --cached --check
git status --short
```
Le scope indexé attendu est :
```text
D Cargo.toml
M VERSION
D crates/knowledge-domain-lib/src/content_family.rs
D deltas/0.0.1/alpha.3.fix.2.md
A deltas/0.1.2/alpha.2.fix.1.md
M docs/plans/001-V0_0_1_FOUNDATION_PLAN.md
M docs/validation/001-VALIDATION_MATRIX.md
D history/0.0.1/alpha.3.fix.1.md
A manifests/0.1.2/alpha.2.fix.1.delete.txt
```
L'ordre exact peut varier ; l'ensemble des chemins doit être identique.
## Transition
### PASS
Produire `history/0.1.2/alpha.2.fix.1.md`, commit/push sous l'identité `0.1.2-alpha.2.fix.1`, puis abandonner le stash préparé à partir de l'ancien HEAD contaminé et réémettre la tranche `alpha.3` sur la baseline corrigée.
La tranche `alpha.3` devra être régénérée ; le stash actuel sert uniquement de sauvegarde de sécurité et ne doit pas devenir la source autoritaire du nouveau delta.
### FAIL
Conserver les résultats réels dans `history/0.1.2/alpha.2.fix.1.md` et poursuivre sous `alpha.2.fix.N`. Ne pas restaurer `alpha.3` tant que l'état PGR publié n'est pas propre.

259
deltas/0.1.2/alpha.2.md Normal file
View File

@@ -0,0 +1,259 @@
<!-- file: deltas/0.1.2/alpha.2.md -->
<!-- version: 1 -->
# Delta 0.1.2-alpha.2 — révision ciblée Java / Gradle
## Baseline et version
Baseline attendue : commit opérateur de `0.1.2-alpha.1`, réalisé après application de `history/0.1.2/alpha.1.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.2-alpha.1
```
Version après application :
```text
0.1.2-alpha.2
```
## Objet
Appliquer la révision normative ciblée décidée après l'audit Games de `alpha.1` sans transformer les choix locaux du corpus en prescriptions générales.
La tranche précise uniquement :
- la distinction entre JDK de build, niveau source et bytecode/runtime supporté ;
- la possibilité pour un JDK plus récent de cibler explicitement un niveau Java plus ancien ;
- l'ownership naturel de `settings.gradle(.kts)`, du build root, des builds de modules et de `gradle.properties` partagé ;
- la nécessité qu'une politique « Gradle système » possède une contrainte effectivement vérifiée ;
- la séparation entre configuration Gradle partagée portable et état local/machine/secrets ;
- la frontière entre règles Java/Gradle générales et overrides Android.
Les sections Maven sont relues et conservées sans nouvel artefact : Games `0.3.6` ne contient aucun projet Maven permettant de justifier une normalisation supplémentaire.
## Scope
REPLACE :
```text
VERSION
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
docs/rules/520-JAVA_MAVEN_GRADLE.md
```
ADD :
```text
deltas/0.1.2/alpha.2.md
```
DELETE : aucun.
`docs/rules/610-ANDROID.md`, `RULES.md`, `ROADMAP.md`, `CHANGELOG.md`, les autres profils, templates, skeletons, validations, scripts et tests restent inchangés.
Aucun `history/0.1.2/alpha.2.md` n'est anticipé.
## Décisions Java
Le contrat existant est conservé et rendu plus explicite :
```text
JDK de build
!= niveau Java du code source
!= niveau de bytecode/runtime minimal supporté
```
Un JDK de build plus récent peut être utilisé avec une cible Java plus ancienne lorsque cette cible est déclarée explicitement par le build et réellement supportée par la toolchain.
PGR ne rend obligatoire ni `--release`, ni une toolchain Java, ni `sourceCompatibility`/`targetCompatibility` pour tous les builds. Le mécanisme concret dépend de Maven, Gradle, du plugin et du projet ; le contrat important est que la compatibilité ne soit pas une conséquence implicite du JDK actif.
Les versions Games observées restent locales : ni JDK 25 LTS ni Java 17 ne deviennent un minimum PGR.
## Décisions Gradle
### Ownership
La responsabilité est explicitée sans imposer le layout Games :
```text
settings.gradle(.kts)
composition du build
politiques globales de résolution lorsqu'elles existent
contraintes de bootstrap/version devant agir avant les projets
build root
plugins, versions et conventions réellement partagés
build de module
plugins, dépendances, sources, tâches et paramètres locaux au module
gradle.properties partagé
propriétés portables, non secrètes et réellement communes
```
Une logique transverse devenue importante peut être extraite dans un script, build logic ou plugin possédé plutôt que dupliquée. Aucun de ces mécanismes n'est rendu obligatoire.
### Gradle système et Wrapper
Le Wrapper reste conditionnel : il est recommandé lorsqu'il apporte une reproductibilité utile, mais son absence dans Games reste `KEEP-LOCAL` et n'est pas généralisée.
Lorsqu'un projet choisit un Gradle système, sa contrainte de compatibilité doit être effectivement vérifiée par le build ou par une gate exécutée par le projet/CI. Une version écrite uniquement dans la documentation ne suffit pas.
PGR ne reprend ni le minimum `9.6.0` ni l'API `GradleVersion.current()` de Games comme règle universelle. Ils constituent une implémentation valide d'une politique locale, pas la forme obligatoire de la vérification.
### Propriétés et état local
Un `gradle.properties` partagé doit rester portable et non secret. Les chemins machine, credentials, secrets et overrides développeur utilisent un mécanisme local approprié et restent hors Git.
Le version catalog reste optionnel. Groovy DSL et Kotlin DSL restent tous deux reconnus ; le choix Groovy de Games reste `KEEP-LOCAL`.
## Maven
Aucun `pom.xml`, Maven Wrapper ou projet Maven n'existe dans le corpus Games autoritaire. Les sections Maven de `520` ont donc uniquement été relues pour vérifier qu'elles restent cohérentes avec la philosophie générale : centraliser ce qui est réellement commun, ne pas imposer un Wrapper par cérémonie, préférer les gates ciblées et ne pas automatiser `clean` sans besoin.
Aucun template, skeleton, audit ou autre artefact Maven n'est ajouté.
## Frontière Android
`610-ANDROID.md` n'est pas modifié.
Les éléments suivants restent hors scope de `0.1.2` :
```text
AGP et sa matrice de compatibilité
compileSdk / targetSdk / minSdk
NDK et ABI
JNI / AAR / Prefab
applicationId / namespace
manifests / resources
APK / AAB / signing
Variant API Android
devices / AVD / smokes Android
contraintes 16 KB
SDL3 et architecture Games
```
`520` documente seulement qu'une plateforme ou un framework peut imposer un override plus étroit sans transformer cet override en minimum Java/Gradle général.
## 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.2-alpha.2'
git cat-file -e HEAD:history/0.1.2/alpha.1.md
test -f history/0.1.2/alpha.1.md
test -f deltas/0.1.2/alpha.2.md
test ! -e history/0.1.2/alpha.2.md
grep -A2 '^## Statut$' history/0.1.2/alpha.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 2 -->' docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
grep -Fx '<!-- version: 3 -->' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -Fx '<!-- version: 2 -->' docs/rules/610-ANDROID.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.2/alpha.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
profile = Path('docs/rules/520-JAVA_MAVEN_GRADLE.md').read_text(encoding='utf-8')
for phrase in (
'Un JDK de build plus récent MAY compiler un projet qui cible un niveau source ou bytecode plus ancien',
'Le simple fait qu\'une compilation réussisse avec le JDK actif ne constitue pas une déclaration de compatibilité.',
'composition du build et inclusion des projets',
'plugins, dépendances, sources, tâches et paramètres propres au module',
'propriétés portables, non secrètes et réellement communes au build',
'effectivement vérifiée',
'Une version seulement écrite dans la documentation sans contrôle exécutable n\'est pas une preuve suffisante',
'Son absence dans un corpus particulier ne constitue pas une règle générale.',
):
assert phrase in profile, phrase
for phrase in (
'AGP',
'`minSdk`',
'`targetSdk`',
'NDK',
'ABI/JNI',
'packaging APK/AAB',
'device/AVD',
):
assert phrase in profile, phrase
plan = Path('docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'## Décision après `alpha.1`',
'La gate opérateur de `alpha.1` est `PASS`',
'`KEEP-LOCAL` : Groovy DSL, absence de Wrapper dans Games, JDK 25 LTS et cible Java 17',
'`OVERRIDE` : matrice AGP/Gradle/JDK et autres contraintes de plateforme Android',
'`DEFER` : version catalog, skeleton Java/Gradle, audit Python Java/Gradle et nouveaux artefacts Maven',
'`alpha.2` est donc bornée à la révision du profil `520`',
):
assert phrase in plan, phrase
android = Path('docs/rules/610-ANDROID.md').read_text(encoding='utf-8')
assert android.startswith('<!-- file: docs/rules/610-ANDROID.md -->\n<!-- version: 2 -->')
for path in (
'docs/templates',
'docs/skeletons',
'scripts',
):
assert Path(path).is_dir(), path
print('0.1.2 alpha.2 Java/Gradle audit: clean (JDK/source/bytecode explicit, Gradle ownership and system-version verification clarified, Android boundary preserved)')
PYGATE
git diff --check
git add VERSION \
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md \
docs/rules/520-JAVA_MAVEN_GRADLE.md \
deltas/0.1.2/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.2/alpha.2.md
M docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
M docs/rules/520-JAVA_MAVEN_GRADLE.md
```
La revue qualitative doit confirmer que :
- aucune version JDK ou Java observée dans Games n'est devenue un minimum général ;
- un Gradle système reste permis seulement avec une contrainte réellement vérifiée ;
- le Wrapper reste conditionnel et le Groovy DSL n'est pas privilégié normativement ;
- `gradle.properties` partagé ne devient pas un emplacement pour secrets ou chemins machine ;
- les sections Maven n'ont pas acquis de règle provenant d'un corpus qui n'exerce pas Maven ;
- aucune responsabilité Android n'a été déplacée hors de `610` ou démarrée prématurément dans `0.1.2` ;
- aucun template, skeleton ou audit supplémentaire n'a été créé pour matérialiser artificiellement la release.
## Transition
### PASS
Produire `history/0.1.2/alpha.2.md`, puis préparer `0.1.2-beta.1` pour la réconciliation finale du profil contre Games, `500-LANGUAGES.md`, `610-ANDROID.md` et les règles générales de validation, ainsi que la décision explicite sur l'absence ou la nécessité d'artefacts supplémentaires.
### FAIL
Consigner le diagnostic réel dans `history/0.1.2/alpha.2.md` et rester dans `alpha.2.fix.N` sauf REPLAN justifié. Le fix MUST rester borné à la révision Java/Gradle et ne doit pas absorber `beta.1` ou le scope Android `0.1.3`.

365
deltas/0.1.2/alpha.3.md Normal file
View File

@@ -0,0 +1,365 @@
<!-- file: deltas/0.1.2/alpha.3.md -->
<!-- version: 1 -->
# Delta 0.1.2-alpha.3 — REPLAN et scission Java / Maven / Gradle
## Baseline et version
Baseline attendue : commit opérateur de `0.1.2-alpha.2.fix.1`, réalisé après application de `history/0.1.2/alpha.2.fix.1.md` avec statut `PASS`. Le fix de récupération doit donc être publié avant application de la présente tranche.
Le hash de ce commit n'est pas anticipé. L'ancien stash `pgr-0.1.2-alpha.3-before-alpha.2-recovery` est uniquement une sauvegarde de l'application effectuée sur le HEAD contaminé ; il ne constitue pas une source autoritaire et doit être abandonné après publication du fix.
Version avant application :
```text
0.1.2-alpha.2.fix.1
```
Version après application :
```text
0.1.2-alpha.3
```
## Motif du REPLAN
La gate de `alpha.2` valide le contenu normatif ajouté à l'ancien profil combiné. La réconciliation préparatoire de `beta.1` révèle toutefois une ambiguïté d'ownership prévue comme déclencheur de REPLAN dans le plan actif.
`500-LANGUAGES.md` autorise un langage et son build tool dans un même profil lorsque leur séparation serait artificielle, mais indique qu'ils SHOULD être séparés lorsque plusieurs build tools interchangeables possèdent chacun des règles propres significatives.
Après `alpha.2`, Maven et Gradle possèdent chacun des contrats substantiels et indépendants : ownership du build, Wrapper, validation et outputs ; Gradle possède en plus sa politique de version système, DSL, propriétés et version catalog. Un profil unique `Java / Maven / Gradle` rend donc l'applicabilité ambiguë : un projet Java n'utilise pas nécessairement les deux build tools, et Gradle n'implique pas nécessairement Java.
La scission devient une correction d'ownership, pas une préférence de taxonomie.
## Scope
REPLACE :
```text
VERSION
RULES.md
ROADMAP.md
docs/000-README.md
docs/architecture/003-RULE_PROFILE_MODEL.md
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
docs/rules/000-README.md
docs/rules/520-JAVA_MAVEN_GRADLE.md
docs/rules/610-ANDROID.md
```
ADD :
```text
docs/rules/520-JAVA.md
docs/rules/521-MAVEN.md
docs/rules/522-GRADLE.md
deltas/0.1.2/alpha.3.md
```
DELETE : aucun.
L'ancien chemin `docs/rules/520-JAVA_MAVEN_GRADLE.md` devient un bridge `SUPERSEDED` non normatif. Il est conservé uniquement parce que des prompts, plans, deltas, histories et études historiques le référencent encore ; ces snapshots ne doivent pas être réécrits a posteriori et les audits de liens doivent rester propres.
Aucun `history/0.1.2/alpha.3.md` n'est anticipé.
## Owners après scission
Le découpage courant devient :
```text
520 Java
521 Maven
522 Gradle
```
### `520-JAVA.md`
Possède uniquement les règles Java :
- politique JDK et compatibilité source/bytecode/runtime ;
- structure `src/main/java` / `src/test/java` ;
- packages, modules, imports et visibilité ;
- interfaces/API, annotations, nullabilité et exceptions ;
- tests Java ;
- composition explicite avec Maven ou Gradle selon le build réellement utilisé.
Il ne possède plus les règles de Wrapper, reactor, Gradle DSL ou outputs des build tools.
### `521-MAVEN.md`
Possède les responsabilités Maven :
- POM parent/root et héritage multi-module ;
- `dependencyManagement` / `pluginManagement` ;
- miroir technique de `VERSION` lorsque Maven l'exige ;
- Maven système versus Wrapper sans cérémonie ;
- validation ciblée puis reactor/`verify` selon le scope ;
- `target/`, état local et futurs audits réellement justifiés.
Games n'exerce toujours aucun projet Maven : la scission ne prétend donc pas avoir validé une nouvelle convention Maven par corpus ; elle isole seulement les règles déjà existantes et cohérentes.
### `522-GRADLE.md`
Possède les responsabilités Gradle validées et clarifiées en `alpha.2` :
- ownership `settings` / root / module / propriétés partagées ;
- contrainte Gradle système effectivement vérifiée ou Wrapper lorsque pertinent ;
- neutralité Groovy/Kotlin DSL ;
- version catalog optionnel ;
- validation ciblée et `clean` non systématique ;
- `.gradle/`, `build/`, état local et futurs audits réellement justifiés.
Le niveau Java reste possédé par `520-JAVA.md` lorsqu'un build Gradle construit du Java.
## Bridge historique
`520-JAVA_MAVEN_GRADLE.md` passe en révision `4` et ne contient plus de règles courantes. Il indique explicitement :
```text
SUPERSEDED
520-JAVA.md owner Java courant
521-MAVEN.md spécialisation Maven courante
522-GRADLE.md spécialisation Gradle courante
```
Il n'est plus référencé par `RULES.md`, les index de règles ou les compositions courantes. Sa seule responsabilité est la compatibilité documentaire des références historiques.
## Frontière Android
`610-ANDROID.md` change uniquement pour refléter la nouvelle composition :
```text
Android + Gradle -> 600 + 610 + 522
Android + Java -> + 520 lorsque Java est réellement présent
```
Une application Android n'applique pas `520` uniquement parce qu'elle utilise Android ou Gradle.
Aucune règle AGP, `compileSdk`, `targetSdk`, `minSdk`, NDK, ABI/JNI, manifests/resources, packaging/signing, device/AVD, 16 KB ou SDL3 n'est réévaluée dans cette tranche. Ce scope reste réservé à `0.1.3`.
## Décision d'artefacts
La scission n'autorise aucun artefact technique supplémentaire.
Restent non justifiés :
```text
skeleton Java/Gradle générique
template Maven ou Gradle générique
audit Python Java/Maven/Gradle
nouveau contrat de validation spécialisé
artefact Maven issu de Games
```
Les trois profils sont des owners normatifs nécessaires à l'applicabilité ; ils ne constituent pas une duplication fonctionnelle du build tool officiel.
## Validation opérateur
Après application du history `PASS`, commit/push de `alpha.2.fix.1`, abandon de l'ancien stash de sécurité, puis application du présent delta régénéré :
```bash
test "$(cat VERSION)" = '0.1.2-alpha.3'
git cat-file -e HEAD:history/0.1.2/alpha.2.fix.1.md
test -f history/0.1.2/alpha.2.md
test -f history/0.1.2/alpha.2.fix.1.md
test -f deltas/0.1.2/alpha.3.md
test ! -e history/0.1.2/alpha.3.md
grep -A2 '^## Statut$' history/0.1.2/alpha.2.md | grep -Fx 'PASS'
grep -A2 '^## Statut$' history/0.1.2/alpha.2.fix.1.md | grep -Fx 'PASS'
test ! -e Cargo.toml
test ! -e crates/knowledge-domain-lib/src/content_family.rs
test ! -e deltas/0.0.1/alpha.3.fix.2.md
test ! -e history/0.0.1/alpha.3.fix.1.md
grep -Fx '<!-- version: 4 -->' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -Fx '`SUPERSEDED` depuis `0.1.2-alpha.3`.' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -Fx '<!-- version: 4 -->' docs/rules/520-JAVA.md
grep -Fx '<!-- version: 1 -->' docs/rules/521-MAVEN.md
grep -Fx '<!-- version: 1 -->' docs/rules/522-GRADLE.md
grep -Fx '<!-- version: 3 -->' docs/rules/610-ANDROID.md
grep -Fx '<!-- version: 7 -->' docs/architecture/003-RULE_PROFILE_MODEL.md
grep -Fx '<!-- version: 3 -->' docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
grep -Fx '<!-- version: 14 -->' RULES.md
grep -Fx '<!-- version: 16 -->' docs/rules/000-README.md
grep -Fx '<!-- version: 33 -->' docs/000-README.md
grep -Fx '<!-- version: 13 -->' ROADMAP.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.2/alpha.2.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
recovery = Path('history/0.1.2/alpha.2.fix.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', recovery)
family = Path('docs/rules/500-LANGUAGES.md').read_text(encoding='utf-8')
for phrase in (
'Un langage et son build tool MAY partager un profil',
'Ils SHOULD être séparés lorsque plusieurs build tools interchangeables possèdent chacun des règles propres significatives.',
'Une spécialisation de build tool ne devient pas une règle du langage entier.',
):
assert phrase in family, phrase
legacy = Path('docs/rules/520-JAVA_MAVEN_GRADLE.md').read_text(encoding='utf-8')
for phrase in (
'`SUPERSEDED` depuis `0.1.2-alpha.3`.',
'Il ne constitue plus un profil sélectionnable',
'520-JAVA.md',
'521-MAVEN.md',
'522-GRADLE.md',
):
assert phrase in legacy, phrase
java = Path('docs/rules/520-JAVA.md').read_text(encoding='utf-8')
for phrase in (
'# Profil Java',
'JDK utilisé pour construire',
'niveau Java du code source',
'niveau de bytecode/runtime minimal supporté',
'Un projet Java construit avec Maven compose normalement',
'Un projet Java construit avec Gradle compose normalement',
):
assert phrase in java, phrase
assert '## Maven' not in java
assert '## Gradle' not in java
maven = Path('docs/rules/521-MAVEN.md').read_text(encoding='utf-8')
for phrase in (
'# Profil Maven',
'POM parent/root',
'PGR MUST NOT ajouter un Maven Wrapper uniquement par cérémonie.',
'./mvnw -pl <module> -am test',
'target/',
):
assert phrase in maven, phrase
gradle = Path('docs/rules/522-GRADLE.md').read_text(encoding='utf-8')
for phrase in (
'# Profil Gradle',
'composition du build et inclusion des projets',
'effectivement vérifiée',
'Groovy DSL et Kotlin DSL sont tous deux reconnus.',
'gradle clean',
):
assert phrase in gradle, phrase
for forbidden in (
'compileSdk',
'targetSdk',
'minSdk',
'NDK',
'ABI/JNI',
'APK/AAB',
'device/AVD',
'SDL3',
):
assert forbidden not in maven, forbidden
assert forbidden not in gradle, forbidden
android = Path('docs/rules/610-ANDROID.md').read_text(encoding='utf-8')
assert '520-JAVA.md' in android
assert '522-GRADLE.md' in android
assert '520-JAVA_MAVEN_GRADLE.md' not in android
architecture = Path('docs/architecture/003-RULE_PROFILE_MODEL.md').read_text(encoding='utf-8')
for phrase in (
'## Scission Java / Maven / Gradle en `0.1.2`',
'520 — Java',
'521 — Maven',
'522 — Gradle',
'GENERAL + 500 + 520 + 522 + 600 + 610',
'bridge `SUPERSEDED` non normatif',
):
assert phrase in architecture, phrase
for current in (
'RULES.md',
'docs/000-README.md',
'docs/rules/000-README.md',
'docs/rules/610-ANDROID.md',
):
assert '520-JAVA_MAVEN_GRADLE.md' not in Path(current).read_text(encoding='utf-8'), current
plan = Path('docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'## Décision après `alpha.2` et REPLAN',
'`alpha.2.fix.1` restaure l\'état PGR attendu',
'alpha.3 scission des owners Java / Maven / Gradle',
'520-JAVA.md',
'521-MAVEN.md',
'522-GRADLE.md',
'bridge documentaire non normatif',
'aucun template, skeleton, audit Java/Gradle ou nouvel artefact Maven n\'est justifié',
):
assert phrase in plan, phrase
for foreign in (
'Cargo.toml',
'crates/knowledge-domain-lib/src/content_family.rs',
'deltas/0.0.1/alpha.3.fix.2.md',
'history/0.0.1/alpha.3.fix.1.md',
):
assert not Path(foreign).exists(), foreign
print('0.1.2 alpha.3 owner split audit: clean (recovery baseline confirmed, Java/Maven/Gradle applicability separated, historical bridge preserved, Android boundary preserved)')
PYGATE
git diff --check
git add -A
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est exactement :
```text
M ROADMAP.md
M RULES.md
M VERSION
A deltas/0.1.2/alpha.3.md
M docs/000-README.md
M docs/architecture/003-RULE_PROFILE_MODEL.md
M docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
M docs/rules/000-README.md
M docs/rules/520-JAVA_MAVEN_GRADLE.md
A docs/rules/520-JAVA.md
A docs/rules/521-MAVEN.md
A docs/rules/522-GRADLE.md
M docs/rules/610-ANDROID.md
```
La revue qualitative doit confirmer que :
- la scission suit une différence réelle d'applicabilité, pas une préférence de taille de fichier ;
- l'ancien fichier est uniquement un bridge `SUPERSEDED` et n'apparaît plus dans les index ou compositions courantes ;
- aucune règle Java n'est perdue et aucune règle Maven/Gradle n'est remontée dans `520-JAVA.md` ;
- Maven et Gradle ne s'appliquent que lorsqu'ils sont réellement utilisés ;
- la preuve Games reste principalement une preuve Gradle/Java et ne devient pas une preuve Maven fictive ;
- aucun minimum JDK, Java ou Gradle propre à Games n'est généralisé ;
- Android ne devient pas une condition d'applicabilité de `522-GRADLE.md` et `610` conserve ses responsabilités ;
- les documents historiques ne sont pas réécrits pour masquer l'ancien owner combiné ;
- aucun template, skeleton, audit ou contrat de validation supplémentaire n'est créé.
## Transition
### PASS
Produire `history/0.1.2/alpha.3.md`, puis préparer `0.1.2-beta.1` pour la réconciliation intégrée des trois owners, la décision finale d'artefacts et les mises à jour documentaires durables nécessaires avant RC.
### FAIL
Consigner le diagnostic réel dans `history/0.1.2/alpha.3.md`, puis produire `alpha.3.fix.N` ou effectuer un nouveau REPLAN si la scission révèle une responsabilité qui ne peut pas être possédée proprement par `520`, `521` ou `522`.

275
deltas/0.1.2/beta.1.md Normal file
View File

@@ -0,0 +1,275 @@
<!-- file: deltas/0.1.2/beta.1.md -->
<!-- version: 1 -->
# Delta 0.1.2-beta.1 — réconciliation intégrée et décision finale d'artefacts
## Baseline et version
Baseline attendue : commit opérateur de `0.1.2-alpha.3`, réalisé après application de `history/0.1.2/alpha.3.md` avec statut `PASS`.
Version avant application :
```text
0.1.2-alpha.3
```
Version après application :
```text
0.1.2-beta.1
```
## Objet
Cette tranche exécute la réconciliation prévue après la scission des owners Java, Maven et Gradle. Elle ne crée aucune nouvelle règle fonctionnelle et ne modifie aucun des profils `520-JAVA.md`, `521-MAVEN.md`, `522-GRADLE.md` ou `610-ANDROID.md`.
La beta confirme que la séparation `520/521/522` résout l'ambiguïté d'applicabilité sans importer les choix locaux Games ni ouvrir le scope Android.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
docs/architecture/003-RULE_PROFILE_MODEL.md
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
```
ADD :
```text
deltas/0.1.2/beta.1.md
```
DELETE : aucun.
Aucun `history/0.1.2/beta.1.md` n'est anticipé.
## Réconciliation des owners
La revue confirme les contrats suivants :
```text
520-JAVA.md Java uniquement
521-MAVEN.md Maven uniquement lorsqu'il est réellement utilisé
522-GRADLE.md Gradle uniquement lorsqu'il est réellement utilisé
```
La composition reste explicite. Un projet Java/Maven applique `520 + 521`; un projet Java/Gradle applique `520 + 522`; un projet Gradle sans Java n'applique pas `520` par simple transitivité.
L'ancien `520-JAVA_MAVEN_GRADLE.md` reste un bridge `SUPERSEDED` non normatif pour la compatibilité documentaire historique et ne redevient pas sélectionnable.
## Réconciliation contre Games
Games fournit une preuve réelle pour Java et Gradle, mais aucune preuve Maven. La beta confirme donc que :
- la séparation JDK de build / niveau source / bytecode-runtime est généralisable ;
- l'ownership `settings` / root / module / propriétés partagées est généralisable ;
- une politique Gradle système doit avoir une contrainte effectivement vérifiée ;
- le Wrapper reste un mécanisme conditionnel de reproductibilité ;
- Groovy DSL et absence de Wrapper restent des choix locaux Games ;
- JDK 25, Java 17, Gradle 9.6.0+ et Gradle 9.7.1 ne deviennent aucun minimum PGR ;
- aucun contenu Maven nouveau n'est déduit d'un corpus qui n'utilise pas Maven.
## Frontière Android
La beta ne modifie pas `610-ANDROID.md`.
Restent explicitement hors du scope `0.1.2` :
```text
AGP
compileSdk / targetSdk / minSdk
SDK / NDK
ABI / JNI
manifests / resources
APK / AAB / signing
Variant API
AVD / devices / smokes Android
contraintes 16 KB
SDL3 et architecture produit Games
```
Ces responsabilités restent réservées à `0.1.3` ou à un owner plus spécifique.
## Décision finale d'artefacts
Aucun artefact technique supplémentaire n'est justifié pour `0.1.2`.
Ne sont donc pas ajoutés :
```text
nouveau contrat docs/validation/
template Java/Maven/Gradle générique
skeleton Java/Gradle générique
audit Python Java/Maven/Gradle
artefact Maven déduit de Games
```
La raison est positive et vérifiable : les trois owners couvrent déjà les responsabilités génériques démontrées, tandis que Java, Maven et Gradle eux-mêmes possèdent les preuves exécutables de compilation/build/test. Ajouter un artefact uniquement pour remplir la release introduirait de la duplication ou une convention insuffisamment éprouvée.
## Documentation durable
La tranche actualise :
- le statut racine de la release ;
- l'index documentaire `0.1.2` ;
- le modèle architectural avec la décision beta durable ;
- le plan actif avec le `PASS` de `alpha.3` et la décision finale d'artefacts.
Aucun changement n'est requis dans `RULES.md`, `docs/rules/000-README.md` ou `ROADMAP.md`, déjà réconciliés pendant `alpha.3`.
## Validation opérateur
Après application du history `PASS` de `alpha.3`, commit/push de `alpha.3`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.2-beta.1'
git cat-file -e HEAD:history/0.1.2/alpha.3.md
test -f history/0.1.2/alpha.3.md
test -f deltas/0.1.2/beta.1.md
test ! -e history/0.1.2/beta.1.md
grep -A2 '^## Statut$' history/0.1.2/alpha.3.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 21 -->' README.md
grep -Fx '<!-- version: 34 -->' docs/000-README.md
grep -Fx '<!-- version: 8 -->' docs/architecture/003-RULE_PROFILE_MODEL.md
grep -Fx '<!-- version: 4 -->' docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
grep -Fx '<!-- version: 4 -->' docs/rules/520-JAVA.md
grep -Fx '<!-- version: 1 -->' docs/rules/521-MAVEN.md
grep -Fx '<!-- version: 1 -->' docs/rules/522-GRADLE.md
grep -Fx '<!-- version: 4 -->' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -Fx '<!-- version: 3 -->' docs/rules/610-ANDROID.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.2/alpha.3.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
java = Path('docs/rules/520-JAVA.md').read_text(encoding='utf-8')
maven = Path('docs/rules/521-MAVEN.md').read_text(encoding='utf-8')
gradle = Path('docs/rules/522-GRADLE.md').read_text(encoding='utf-8')
legacy = Path('docs/rules/520-JAVA_MAVEN_GRADLE.md').read_text(encoding='utf-8')
android = Path('docs/rules/610-ANDROID.md').read_text(encoding='utf-8')
architecture = Path('docs/architecture/003-RULE_PROFILE_MODEL.md').read_text(encoding='utf-8')
plan = Path('docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
assert '# Profil Java' in java
assert '# Profil Maven' in maven
assert '# Profil Gradle' in gradle
assert '`SUPERSEDED` depuis `0.1.2-alpha.3`.' in legacy
assert 'Il ne constitue plus un profil sélectionnable' in legacy
for current in ('RULES.md', 'docs/000-README.md', 'docs/rules/000-README.md', 'docs/rules/610-ANDROID.md'):
assert '520-JAVA_MAVEN_GRADLE.md' not in Path(current).read_text(encoding='utf-8'), current
for local_choice in (
'JDK 25',
'source/target 17',
'Gradle 9.6.0',
'Gradle 9.7.1',
'AGP 9.4.0',
):
assert local_choice not in java, local_choice
assert local_choice not in maven, local_choice
assert local_choice not in gradle, local_choice
for android_term in (
'compileSdk',
'targetSdk',
'minSdk',
'NDK',
'ABI/JNI',
'APK/AAB',
'device/AVD',
'SDL3',
):
assert android_term not in maven, android_term
assert android_term not in gradle, android_term
assert 'Matrice AGP / Gradle / JDK' in android
assert '`compileSdk`, `targetSdk` et `minSdk`' in android
for phrase in (
'## Réconciliation beta de Java / Maven / Gradle en `0.1.2`',
'aucune preuve Maven réelle',
'Aucun nouveau contrat sous `docs/validation/`, template, skeleton ou audit Python Java/Maven/Gradle n\'est justifié.',
):
assert phrase in architecture, phrase
for phrase in (
'## Décision après `alpha.3` et réconciliation `beta.1`',
'La gate opérateur de `alpha.3` est `PASS`',
'aucun artefact technique supplémentaire',
'aucun corpus Maven',
'`0.1.3`',
):
assert phrase in plan, phrase
for foreign in (
'Cargo.toml',
'crates/knowledge-domain-lib/src/content_family.rs',
'deltas/0.0.1/alpha.3.fix.2.md',
'history/0.0.1/alpha.3.fix.1.md',
):
assert not Path(foreign).exists(), foreign
print('0.1.2 beta.1 reconciliation audit: clean (owners stable, Games-local choices not generalized, no extra artifacts justified, Android boundary preserved)')
PYGATE
git diff --check
git add README.md VERSION \
docs/000-README.md \
docs/architecture/003-RULE_PROFILE_MODEL.md \
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md \
deltas/0.1.2/beta.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est exactement :
```text
M README.md
M VERSION
A deltas/0.1.2/beta.1.md
M docs/000-README.md
M docs/architecture/003-RULE_PROFILE_MODEL.md
M docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
```
La revue qualitative doit confirmer que :
- aucun choix local Games n'est promu comme minimum générique ;
- Maven n'est pas présenté comme validé par Games ;
- les owners `520/521/522` restent indépendants et composables ;
- aucun nouveau fichier technique n'est ajouté pour satisfaire une structure théorique ;
- Android reste entièrement hors du scope fonctionnel de `0.1.2` ;
- la documentation durable reflète la scission et la décision d'artefacts sans réécrire les snapshots historiques.
## Transition
### PASS
Produire `history/0.1.2/beta.1.md`, puis préparer `0.1.2-rc.1` pour le gel de scope et la release gate complète.
### FAIL
Consigner le diagnostic réel dans `history/0.1.2/beta.1.md`, puis produire `beta.1.fix.N` ou effectuer un REPLAN uniquement si un défaut d'ownership ou de frontière ne peut pas être corrigé localement.

359
deltas/0.1.2/rc.1.md Normal file
View File

@@ -0,0 +1,359 @@
<!-- file: deltas/0.1.2/rc.1.md -->
<!-- version: 1 -->
# Delta 0.1.2-rc.1 — gel du scope et gate de release candidate
## Baseline et version
Baseline attendue : commit opérateur de `0.1.2-beta.1`, réalisé après application de `history/0.1.2/beta.1.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.2-beta.1
```
Version après application :
```text
0.1.2-rc.1
```
## Objet et gel
La RC gèle le scope fonctionnel de `0.1.2` sur :
- `520-JAVA.md` comme owner du langage Java, de la compatibilité JDK/source/bytecode-runtime, de la structure, de l'API et des tests Java ;
- `521-MAVEN.md` comme spécialisation Maven uniquement lorsqu'un projet utilise réellement Maven ;
- `522-GRADLE.md` comme spécialisation Gradle uniquement lorsqu'un projet utilise réellement Gradle ;
- la distinction JDK de build / niveau Java source / niveau de bytecode-runtime sans généraliser les versions particulières de Games ;
- l'ownership Gradle `settings` / root / modules / propriétés partagées, avec séparation de l'état local ;
- le Wrapper comme mécanisme conditionnel de reproductibilité et Gradle système comme politique valide seulement lorsque sa contrainte est effectivement vérifiée ;
- l'ancien `520-JAVA_MAVEN_GRADLE.md` comme bridge `SUPERSEDED` non normatif afin de préserver les liens historiques ;
- la décision beta qu'aucun template, skeleton, audit Python, contrat de validation ou artefact Maven supplémentaire n'est justifié par le corpus disponible ;
- la frontière Android : AGP, SDK/NDK, ABI/JNI, manifests/resources, packaging/signing, devices/AVD, contraintes 16 KB et SDL3 restent hors des owners Java/Maven/Gradle et sont réévalués séparément en `0.1.3`.
Le changelog reçoit une entrée candidate `0.1.2` orientée utilisateurs. Le prompt `009-V0_1_3_START_PROMPT.md` est préparé pour la prochaine cible engagée Android à partir de Games.
Aucune nouvelle règle fonctionnelle n'entre dans cette RC. Les owners `520/521/522`, le bridge historique, `610-ANDROID.md`, les templates, skeletons, validations et scripts d'audit sont vérifiés mais non modifiés.
## Scope
REPLACE :
```text
VERSION
CHANGELOG.md
docs/000-README.md
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
```
ADD :
```text
deltas/0.1.2/rc.1.md
prompts/009-V0_1_3_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.2-rc.1'
git cat-file -e HEAD:history/0.1.2/beta.1.md
test -f history/0.1.2/beta.1.md
test -f deltas/0.1.2/rc.1.md
test -f prompts/009-V0_1_3_START_PROMPT.md
test ! -e history/0.1.2/rc.1.md
grep -A2 '^## Statut$' history/0.1.2/beta.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 14 -->' CHANGELOG.md
grep -Fx '## 0.1.2 (candidate)' CHANGELOG.md
grep -Fx '<!-- version: 35 -->' docs/000-README.md
grep -Fx '<!-- version: 5 -->' docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
grep -Fx '<!-- version: 13 -->' ROADMAP.md
grep -Fx '<!-- version: 1 -->' prompts/009-V0_1_3_START_PROMPT.md
grep -Fx '<!-- version: 4 -->' docs/rules/520-JAVA.md
grep -Fx '<!-- version: 1 -->' docs/rules/521-MAVEN.md
grep -Fx '<!-- version: 1 -->' docs/rules/522-GRADLE.md
grep -Fx '<!-- version: 4 -->' docs/rules/520-JAVA_MAVEN_GRADLE.md
grep -Fx '<!-- version: 3 -->' docs/rules/610-ANDROID.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": "PASS",
"alpha.2.fix.1.md": "PASS",
"alpha.3.md": "PASS",
"beta.1.md": "PASS",
}
histories = {path.name for path in Path("history/0.1.2").glob("*.md")}
assert histories == set(expected), histories
for name, status in expected.items():
text = Path("history/0.1.2", 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.2").glob("*.md")}
assert deltas == set(expected) | {"rc.1.md"}, deltas
changelog = Path("CHANGELOG.md").read_text(encoding="utf-8")
assert "## 0.1.2 (candidate)" in changelog
section = changelog.split("## 0.1.2 (candidate)", 1)[1].split("## 0.1.1", 1)[0]
for phrase in (
"trois owners indépendants",
"520-JAVA",
"521-MAVEN",
"522-GRADLE",
"JDK utilisé pour construire",
"Wrapper",
"Gradle système",
"SUPERSEDED",
"réévaluation pratique reste la cible distincte `0.1.3`",
):
assert phrase in section, phrase
for forbidden in (
"alpha.1",
"alpha.2",
"alpha.3",
"beta.1",
"rc.1",
):
assert forbidden not in section, forbidden
java = Path("docs/rules/520-JAVA.md").read_text(encoding="utf-8")
maven = Path("docs/rules/521-MAVEN.md").read_text(encoding="utf-8")
gradle = Path("docs/rules/522-GRADLE.md").read_text(encoding="utf-8")
legacy = Path("docs/rules/520-JAVA_MAVEN_GRADLE.md").read_text(encoding="utf-8")
android = Path("docs/rules/610-ANDROID.md").read_text(encoding="utf-8")
assert "# Profil Java" in java
assert "# Profil Maven" in maven
assert "# Profil Gradle" in gradle
assert "`SUPERSEDED` depuis `0.1.2-alpha.3`." in legacy
assert "Il ne constitue plus un profil sélectionnable" in legacy
for current in (
"RULES.md",
"docs/000-README.md",
"docs/rules/000-README.md",
"docs/rules/610-ANDROID.md",
):
assert "520-JAVA_MAVEN_GRADLE.md" not in Path(current).read_text(encoding="utf-8"), current
for local_choice in (
"JDK 25",
"source/target 17",
"Gradle 9.6.0",
"Gradle 9.7.1",
"AGP 9.4.0",
):
assert local_choice not in java, local_choice
assert local_choice not in maven, local_choice
assert local_choice not in gradle, local_choice
for android_term in (
"compileSdk",
"targetSdk",
"minSdk",
"NDK",
"ABI/JNI",
"APK/AAB",
"device/AVD",
"SDL3",
):
assert android_term not in maven, android_term
assert android_term not in gradle, android_term
for phrase in (
"Matrice AGP / Gradle / JDK",
"`compileSdk`, `targetSdk` et `minSdk`",
"ABI et code natif",
"Signing et secrets",
):
assert phrase in android, phrase
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
assert "- `( ) 0.1.2`" in roadmap
for version in ("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
plan = Path("docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md").read_text(encoding="utf-8")
for phrase in (
"### beta.1 — réconciliation et décision d'artefacts",
"Statut opérateur : **PASS**.",
"### rc.1 — release candidate",
"Statut opérateur : **à valider**.",
"prompts/009-V0_1_3_START_PROMPT.md",
"Aucune nouvelle règle fonctionnelle n'entre en RC",
):
assert phrase in plan, phrase
prompt = Path("prompts/009-V0_1_3_START_PROMPT.md").read_text(encoding="utf-8")
for phrase in (
"archive source téléchargée depuis le tag Gitea `v0.1.2`",
"pgr-0.1.2-publish.001-report.md",
"0.1.3-alpha.1",
"ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8",
"610-ANDROID.md",
"520-JAVA.md",
"522-GRADLE.md",
"ADOPT / KEEP-LOCAL / OVERRIDE / DEFER",
"Android Gradle Plugin / Gradle / JDK",
"compileSdk",
"targetSdk",
"minSdk",
"NDK",
"ABI",
"JNI",
"signing",
"16 KB",
"réservé à `0.1.4`",
"adoption Games `0.1.5`",
):
assert phrase in prompt, phrase
for forbidden in (
"Cargo.toml",
"crates/knowledge-domain-lib/src/content_family.rs",
"deltas/0.0.1/alpha.3.fix.2.md",
"history/0.0.1/alpha.3.fix.1.md",
):
assert not Path(forbidden).exists(), forbidden
java_related = sorted(
str(path)
for root in (Path("docs/templates"), Path("docs/skeletons"), Path("docs/validation"), Path("scripts"))
for path in root.rglob("*")
if path.is_file() and any(word in path.name.lower() for word in ("java", "maven", "gradle"))
)
assert java_related == [], java_related
print("0.1.2 rc.1 integration audit: clean (5 prior histories, frozen Java/Maven/Gradle owners, candidate changelog and prompt 009 verified, Android boundary preserved)")
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 et la parsabilité des templates de baseline sans prétendre simuler une toolchain Java/Maven/Gradle absente :
```bash
python3 -B - <<'PYHYGIENE'
from pathlib import Path
import json
import tomllib
for path in sorted(Path("templates/rust-cargo").rglob("*.toml")):
tomllib.loads(path.read_text(encoding="utf-8"))
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.2 rc.1 text/template hygiene: clean")
PYHYGIENE
git diff --check
git add VERSION CHANGELOG.md docs/000-README.md \
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md \
prompts/009-V0_1_3_START_PROMPT.md \
deltas/0.1.2/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.2/rc.1.md
M docs/000-README.md
M docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
A prompts/009-V0_1_3_START_PROMPT.md
```
## Revue opérateur complémentaire
Confirmer que :
- le scope normatif Java/Maven/Gradle est gelé ;
- aucun owner `520/521/522`, bridge historique, profil Android, template, skeleton, contrat de validation ou script d'audit n'est modifié par la RC ;
- le changelog candidat décrit les capacités utiles de `0.1.2` sans recopier les tranches internes ni l'incident de chaîne de commit ;
- aucun choix local Games n'est promu comme minimum Java/Maven/Gradle générique ;
- Maven n'est pas présenté comme éprouvé par Games ;
- l'absence d'artefacts Java/Maven/Gradle supplémentaires reste une décision positive fondée sur le corpus, pas un oubli ;
- Android reste hors du scope fonctionnel de `0.1.2` et le prompt `009` ne devient exécutable qu'après publication vérifiée de `v0.1.2` ;
- le prompt `009` ne transforme pas SDL3, les jeux ou Tauri Android en règles Android générales ;
- le skeleton Tauri reste réservé à `0.1.4` et l'adoption Games à `0.1.5` ;
- `0.1.8` n'est pas réservé ;
- aucune preuve `javac`, Maven, Gradle ou Android n'est revendiquée localement alors que PGR ne contient pas d'artefact exécutable correspondant dans cette RC.
## Transition
### PASS
Produire `history/0.1.2/rc.1.md`, l'appliquer puis committer/pousser `rc.1`. Continuer avec `0.1.2-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.2/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`.

288
deltas/0.1.2/rel.1.md Normal file
View File

@@ -0,0 +1,288 @@
<!-- file: deltas/0.1.2/rel.1.md -->
<!-- version: 1 -->
# Delta 0.1.2 rel.1 — promotion stable pré-tag
## Baseline et version
Baseline : `0.1.2-rc.1`, avec `history/0.1.2/rc.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.1.2-rc.1
```
Version après application :
```text
0.1.2
```
`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.2` 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 `008` historique. Aucun owner Java/Maven/Gradle, bridge historique, profil Android, template, skeleton, validation ou script d'audit n'est modifié.
La validation de cette tranche est **pré-tag**. Le tag `v0.1.2`, son archive source Gitea et le rapport `pgr-0.1.2-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.2` et la publication réelle du tag.
## Scope
REPLACE :
```text
VERSION
README.md
ROADMAP.md
CHANGELOG.md
docs/000-README.md
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
```
ADD :
```text
deltas/0.1.2/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.2/rc.1.md` :
```bash
test "$(cat VERSION)" = '0.1.2'
git cat-file -e HEAD:history/0.1.2/rc.1.md
test -f history/0.1.2/rc.1.md
test -f deltas/0.1.2/rel.1.md
test -f prompts/009-V0_1_3_START_PROMPT.md
test ! -e history/0.1.2/rel.1.md
grep -A2 '^## Statut$' history/0.1.2/rc.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 22 -->' README.md
grep -Fx '<!-- version: 14 -->' ROADMAP.md
grep -Fx '<!-- version: 15 -->' CHANGELOG.md
grep -Fx '<!-- version: 36 -->' docs/000-README.md
grep -Fx '<!-- version: 6 -->' docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
grep -F -- '- `(x) 0.1.2`' ROADMAP.md
grep -Fx '## 0.1.2' CHANGELOG.md
grep -F 'avec `0.1.2` d’owners Java, Maven et Gradle séparés et composables' README.md
grep -F 'plan historique de la stable `0.1.2`' README.md docs/000-README.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
expected = {
"alpha.1.md": "PASS",
"alpha.2.md": "PASS",
"alpha.2.fix.1.md": "PASS",
"alpha.3.md": "PASS",
"beta.1.md": "PASS",
"rc.1.md": "PASS",
}
for name, status in expected.items():
delta = Path("deltas/0.1.2", name)
history = Path("history/0.1.2", 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.2").glob("*.md")} - {
path.name for path in Path("history/0.1.2").glob("*.md")
}
assert pending == {"rel.1.md"}, pending
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
assert "- `(x) 0.1.2`" in roadmap
for version in ("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.2" in changelog.splitlines()
assert "## 0.1.2 (candidate)" not in changelog
section = changelog.split("## 0.1.2", 1)[1].split("## 0.1.1", 1)[0]
for phrase in (
"trois owners indépendants",
"520-JAVA",
"521-MAVEN",
"522-GRADLE",
"JDK utilisé pour construire",
"Wrapper",
"Gradle système",
"SUPERSEDED",
"réévaluation pratique reste la cible distincte `0.1.3`",
):
assert phrase in section, phrase
for forbidden in ("alpha.1", "alpha.2", "alpha.3", "beta.1", "rc.1", "rel.1"):
assert forbidden not in section, forbidden
readme = Path("README.md").read_text(encoding="utf-8")
assert "avec `0.1.2` d’owners Java, Maven et Gradle séparés et composables" in readme
assert "plan historique de la stable `0.1.2`" in readme
index = Path("docs/000-README.md").read_text(encoding="utf-8")
assert "plan historique de la stable `0.1.2`" in index
assert "à exécuter uniquement après publication et vérification post-tag de `v0.1.2`" in index
plan = Path("docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md").read_text(encoding="utf-8")
assert "Plan historique de la stable `0.1.2`" in plan
assert "### rc.1 — release candidate\n\nStatut opérateur : **PASS**." in plan
assert "history/0.1.2/rel.1.md" in plan
assert "pgr-0.1.2-publish.001-report.md" in plan
assert "commit `0.1.2` avant le tag `v0.1.2`" in plan
prompt = Path("prompts/009-V0_1_3_START_PROMPT.md").read_text(encoding="utf-8")
assert "tag Gitea `v0.1.2`" in prompt
assert "pgr-0.1.2-publish.001-report.md" in prompt
assert "0.1.3-alpha.1" in prompt
assert "réservé à `0.1.4`" in prompt
assert "adoption Games `0.1.5`" in prompt
for path, version in (
("docs/rules/520-JAVA.md", 4),
("docs/rules/521-MAVEN.md", 1),
("docs/rules/522-GRADLE.md", 1),
("docs/rules/520-JAVA_MAVEN_GRADLE.md", 4),
("docs/rules/610-ANDROID.md", 3),
):
lines = Path(path).read_text(encoding="utf-8").splitlines()
assert lines[1] == f"<!-- version: {version} -->", (path, lines[1])
legacy = Path("docs/rules/520-JAVA_MAVEN_GRADLE.md").read_text(encoding="utf-8")
assert "`SUPERSEDED` depuis `0.1.2-alpha.3`." in legacy
assert "Il ne constitue plus un profil sélectionnable" in legacy
for current in ("RULES.md", "docs/000-README.md", "docs/rules/000-README.md", "docs/rules/610-ANDROID.md"):
assert "520-JAVA_MAVEN_GRADLE.md" not in Path(current).read_text(encoding="utf-8"), current
for forbidden in (
"Cargo.toml",
"crates/knowledge-domain-lib/src/content_family.rs",
"deltas/0.0.1/alpha.3.fix.2.md",
"history/0.0.1/alpha.3.fix.1.md",
):
assert not Path(forbidden).exists(), forbidden
java_related = sorted(
str(path)
for root in (Path("docs/templates"), Path("docs/skeletons"), Path("docs/validation"), Path("scripts"))
for path in root.rglob("*")
if path.is_file() and any(word in path.name.lower() for word in ("java", "maven", "gradle"))
)
assert java_related == [], java_related
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.2 rel.1 stable gate audit: clean (6 prior histories, rel.1 pending, stable Java/Maven/Gradle 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
import tomllib
for path in sorted(Path("templates/rust-cargo").rglob("*.toml")):
tomllib.loads(path.read_text(encoding="utf-8"))
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.2 rel.1 text/template hygiene: clean")
PYHYGIENE
git diff --check
git add VERSION README.md ROADMAP.md CHANGELOG.md docs/000-README.md \
docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md \
deltas/0.1.2/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.2/rel.1.md
M docs/000-README.md
M docs/plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md
```
La RC a déjà reconfirmé les owners gelés, la frontière Android, le contrat du prompt `009` et l'absence d'artefacts Java/Maven/Gradle supplémentaires. Comme `rel.1` ne modifie aucun artefact technique, la promotion stable rejoue les tests PGR, les audits documentaires et l'hygiène des templates sans simuler de toolchain Java/Maven/Gradle absente du dépôt.
## Revue opérateur complémentaire
Confirmer que :
- le scope fonctionnel de `rc.1` ne change pas ;
- `0.1.2` est présenté comme stable de manière cohérente dans VERSION/README/ROADMAP/CHANGELOG/index/plan ;
- les histories `alpha.1`, `alpha.2`, `alpha.2.fix.1`, `alpha.3`, `beta.1` et `rc.1` restent conservés avec leur statut réel `PASS` ;
- `520-JAVA`, `521-MAVEN` et `522-GRADLE` restent gelés et l'ancien owner combiné reste uniquement un bridge historique `SUPERSEDED` ;
- aucune version particulière de Games ne devient un minimum PGR ;
- le profil Android reste inchangé et `0.1.3` conserve seul sa réévaluation pratique ;
- le skeleton Tauri reste réservé au réexamen `0.1.4` et l'adoption Games à `0.1.5` ;
- la roadmap engagée `0.1.3` à `0.1.7` reste intacte sans `0.1.8` ;
- le prompt `009` reste conditionnel à une vraie publication de `v0.1.2` 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.2/rel.1.md`, l'appliquer, puis créer le commit stable sous le message exact :
```text
0.1.2
```
Après push de la branche canonique, créer et publier le tag annoté `v0.1.2`. 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.2-publish.001-report.md` à partir de preuves réelles.
Le prompt `009-V0_1_3_START_PROMPT.md` ne devient la reprise effective de `0.1.3` qu'après un rapport post-tag `PASS`.
### FAIL
Consigner le diagnostic réel dans `history/0.1.2/rel.1.md`, ne pas créer le tag et corriger uniquement la fermeture dans `rel.1.fix.1` avant toute publication.

247
deltas/0.1.3/alpha.1.md Normal file
View File

@@ -0,0 +1,247 @@
<!-- file: deltas/0.1.3/alpha.1.md -->
<!-- version: 1 -->
# Delta 0.1.3-alpha.1 — audit de stable et cadrage Android
## Baseline et sources
Baseline PGR autoritaire : archive source téléchargée depuis le tag Gitea `v0.1.2`, accompagnée du rapport externe `pgr-0.1.2-publish.001-report.md` avec statut `PASS`.
SHA-256 vérifiés sur les fichiers réellement fournis :
```text
pgr-v0.1.2(1).zip 0ef8facab0c6f92ca427f5f13d38d6c4a4c1cc16174a20ecdab48991bd88d0e6
pgr-0.1.2-publish.001-report.md 0f6b4e2a685a957fa647a7db009320ada0fc67948737d8344cc3773bcaeb6a9c
games-v0.3.6(2).zip ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8
```
Les archives locales PGR et Games comportent respectivement `(1)` et `(2)` dans leur nom, mais leurs empreintes correspondent exactement aux baselines canoniques `pgr-v0.1.2.zip` et `games-v0.3.6.zip` attendues par le rapport/prompt.
Version avant application :
```text
0.1.2
```
Version après application :
```text
0.1.3-alpha.1
```
## Objet
Exécuter `prompts/009-V0_1_3_START_PROMPT.md` : vérifier intégralement la stable `v0.1.2` et son rapport post-tag, auditer le corpus Games autoritaire sur Android et ses preuves historiques, relire `610-ANDROID.md`, `520-JAVA.md`, `522-GRADLE.md`, `600-PLATFORMS.md`, la validation générale et la revue d'horizon, puis créer le plan `0.1.3` avant toute normalisation Android importante.
`alpha.1` reste un gate de cadrage. Aucune règle Android, règle Java/Gradle, validation spécialisée, template, skeleton ou audit nouveau n'est encore créé ou modifié.
## Résultat de l'audit d'intake
La stable PGR et son rapport post-tag concordent : SHA-256 attendu, CRC propre, racine unique `pgr/`, `316` entrées, `276` fichiers, `40` répertoires, aucun symlink, absence normale de `.git` et `VERSION=0.1.2`.
Le rapport `publish.001` est `PASS` et confirme le commit stable `585b508578aae337f6940110d4ca47c694a052d5`, l'objet tag annoté `cea2c7a06cde844ffa7411f73bb22685a3214414` et la déréférence de `v0.1.2` vers le commit stable.
La suite PGR donne `48/48` tests `PASS`. Les audits Markdown sont propres : `250` fichiers pour les headers, `10` tables sur `250` fichiers et `307` liens locaux sur `250` fichiers. Les templates TOML Rust/Cargo et JSON Web contrôlés sont parsables.
Les `90` couples delta/history de `0.0.1` à `0.1.2` sont complets. Les sept histories `0.1.2` sont tous `PASS`, y compris `alpha.2.fix.1` qui conserve la récupération historique de contamination inter-projet.
Le corpus Games fourni possède exactement le SHA canonique attendu, `652` entrées, `502` fichiers, `150` répertoires et aucun symlink. Ses audits statiques principaux sont propres : règles Rust, exports, workspace, tableaux Markdown et layout de distribution.
Le sous-projet Android natif exerce un build Gradle multi-module sous `Android/` avec `common`, `game-reflex-poc` et `game-snake-poc`, quatre sources Java, manifests/resources, namespaces/application IDs, configuration locale ignorée et scripts Gradle communs.
La baseline Games utilise AGP `9.4.0`, Gradle système `>= 9.6.0`, JDK de build compatible `>= 17`, niveau Java source/target `17`, `compileSdk 36`, `targetSdk 36`, `minSdk 21`, NDK `28.2.13676358` et SDL3 `3.4.16`. Ces valeurs restent des décisions et preuves Games, pas des minima PGR.
Les histories Games démontrent le passage d'une preuve initiale Wrapper/JDK 17 vers un Gradle système avec minimum exécutable et JDK courant, puis des builds réels avec Temurin `25.0.4.1 LTS` + Gradle `9.7.1` tout en conservant Java `17` comme niveau source/target.
Le pipeline natif Games exerce `cargo ndk`, JNI, SDL3 et quatre ABI (`arm64-v8a`, `armeabi-v7a`, `x86_64`, `x86`). Les histories prouvent APK Debug, AAB Release, contenu natif packagé, smokes AVD x86_64 et appareil ARM64 réel, runtime API 21 ainsi qu'une preuve `PAGE_SIZE=16384` sur Android 15/API 35 x86_64.
Ces responsabilités spécialisées ne sont pas copiées dans PGR. Le plan classe les décisions avec `ADOPT / KEEP-LOCAL / OVERRIDE / DEFER`, conserve Tauri en `DEFER` jusqu'à `0.1.4`, l'adoption Games jusqu'à `0.1.5` et prévoit une vérification des exigences Android officielles courantes avant toute normalisation de contraintes évolutives telles que 16 KB.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
```
ADD :
```text
docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
deltas/0.1.3/alpha.1.md
```
DELETE : aucun.
`RULES.md`, `ROADMAP.md`, `CHANGELOG.md`, `docs/rules/610-ANDROID.md`, `docs/rules/520-JAVA.md`, `docs/rules/522-GRADLE.md`, `docs/rules/600-PLATFORMS.md`, les autres règles, templates, skeletons, validations, scripts, studies, prompts et histories existants restent inchangés dans `alpha.1`.
Aucun `history/0.1.3/alpha.1.md` n'est anticipé avant la gate opérateur.
## Validation opérateur
Après application sur la stable `0.1.2`, depuis la racine du dépôt :
```bash
test "$(cat VERSION)" = '0.1.3-alpha.1'
test -f docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
test -f deltas/0.1.3/alpha.1.md
test ! -e history/0.1.3/alpha.1.md
grep -Fx '<!-- version: 23 -->' README.md
grep -Fx '<!-- version: 37 -->' docs/000-README.md
grep -F '009-V0_1_3_ANDROID_REEVALUATION_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,
'0.1.1': 11,
'0.1.2': 7,
}
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.2').glob('*.md'):
text = path.read_text(encoding='utf-8')
match = re.search(r'## Statut\s+(?:`?)(PASS|FAIL|PARTIAL|BLOCKED)', text)
assert match is not None, path
statuses[path.name] = match.group(1)
assert len(statuses) == 7, statuses
assert set(statuses.values()) == {'PASS'}, statuses
assert statuses['alpha.2.fix.1.md'] == 'PASS'
assert statuses['rel.1.md'] == 'PASS'
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
assert '- `(x) 0.1.2`' in roadmap
for release in range(3, 8):
assert f'- `( ) 0.1.{release}`' in roadmap, release
assert '0.1.8' not in roadmap
assert 'skeleton Tauri jusqu\'au réexamen 0.1.4' in roadmap
prompt = Path('prompts/009-V0_1_3_START_PROMPT.md').read_text(encoding='utf-8')
for phrase in (
'Version cible : `0.1.3`',
'Première tranche attendue : `0.1.3-alpha.1`',
'ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8',
'ADOPT / KEEP-LOCAL / OVERRIDE / DEFER',
'structure `Android/`',
'compileSdk`, `targetSdk` et `minSdk',
'alignement mémoire/16 KB',
'skeleton Tauri, réservé à `0.1.4`',
"démarrer l'adoption Games `0.1.5`",
):
assert phrase in prompt, phrase
android = Path('docs/rules/610-ANDROID.md').read_text(encoding='utf-8')
assert android.startswith('<!-- file: docs/rules/610-ANDROID.md -->\n<!-- version: 3 -->')
for phrase in (
'Android n\'implique pas à lui seul l\'applicabilité du profil Java.',
'Matrice AGP / Gradle / JDK',
'`compileSdk`, `targetSdk` et `minSdk`',
'ABI et code natif',
'Niveaux de tests Android',
'APK, AAB et artefacts de distribution',
):
assert phrase in android, phrase
assert Path('docs/rules/520-JAVA.md').read_text(encoding='utf-8').startswith(
'<!-- file: docs/rules/520-JAVA.md -->\n<!-- version: 4 -->'
)
assert Path('docs/rules/522-GRADLE.md').read_text(encoding='utf-8').startswith(
'<!-- file: docs/rules/522-GRADLE.md -->\n<!-- version: 1 -->'
)
assert Path('docs/rules/600-PLATFORMS.md').read_text(encoding='utf-8').startswith(
'<!-- file: docs/rules/600-PLATFORMS.md -->\n<!-- version: 1 -->'
)
plan = Path('docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'Classification initiale des décisions Games',
'`ADOPT`',
'`KEEP-LOCAL`',
'`OVERRIDE`',
'`DEFER`',
'alpha.2 — structure, composition et contrats Android de base',
'alpha.3 — natif, packaging, distribution et validation',
'beta.1 — réconciliation et décision d\'artefacts',
'AGP `9.4.0`',
'Gradle système `>= 9.6.0`',
'NDK `r28c`',
'PAGE_SIZE=16384',
'documentation Android officielle courante',
'0.1.4 — domaine Tauri',
'0.1.5',
):
assert phrase in plan, phrase
assert not Path('docs/validation/006-ANDROID_VALIDATION.md').exists()
assert not Path('history/0.1.3/alpha.1.md').exists()
print('0.1.3 alpha.1 structural audit: clean (90 prior pairs, Games Android classified, Tauri/adoption boundaries preserved)')
PY
git diff --check
git add VERSION README.md docs/000-README.md \
docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md \
deltas/0.1.3/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.3/alpha.1.md
M docs/000-README.md
A docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
```
La revue opérateur doit également confirmer que :
- `alpha.1` n'a pas modifié `610-ANDROID.md` avant validation du cadrage ;
- les versions exactes Games (AGP/Gradle/JDK/SDK/NDK/SDL3) restent des preuves ou choix locaux, pas des contraintes PGR universelles ;
- `Android/` reste une convention de séparation multi-plateforme et n'est pas imposé artificiellement à un dépôt Android-only ;
- Java reste un owner composé seulement lorsqu'il existe réellement du code Java ;
- les quatre ABI, JNI, `cargo ndk`, SDL3, Activities et assets Games restent des responsabilités produit/framework/spécialisation ;
- aucune exigence 16 KB n'est normalisée sans vérification des sources Android officielles courantes ;
- aucun nouveau template, audit, skeleton ou contrat de validation Android n'est créé par symétrie ;
- Games reste un corpus externe non modifié et son adoption reste réservée à `0.1.5` ;
- le skeleton Tauri reste `DEFER` jusqu'à `0.1.4` ;
- aucun nouveau numéro au-delà de `0.1.7` n'est réservé.
## Transition
### PASS
Produire `history/0.1.3/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.3-alpha.2` consacré à la structure, la composition et aux contrats Android de base définis par le plan, sans absorber encore les détails natifs/packaging de `alpha.3`.
Après remise du history, fournir automatiquement le bloc opérateur exact pour appliquer le history, committer/pusher `0.1.3-alpha.1`, puis seulement appliquer le delta suivant conformément à `docs/templates/006-OPERATOR_COMMAND_HANDOFF.md`.
### FAIL
Consigner le résultat réel dans le history, puis ouvrir `0.1.3-alpha.1.fix.1` ou un REPLAN selon la cause. Aucun changement prévu pour `alpha.2` ne doit être absorbé silencieusement dans le fix.

198
deltas/0.1.3/alpha.2.md Normal file
View File

@@ -0,0 +1,198 @@
<!-- file: deltas/0.1.3/alpha.2.md -->
<!-- version: 1 -->
# Delta 0.1.3-alpha.2 — contrats Android de base
## Baseline
Ce delta s'applique après :
```text
0.1.3-alpha.1
+ history/0.1.3/alpha.1.md PASS
+ commit/push complet de la tranche alpha.1
```
Il ne doit pas être appliqué avant l'intégration du history `alpha.1`.
## Objet
Réviser le profil Android uniquement sur les contrats de base démontrés par le corpus Games et confirmés par la documentation Android officielle courante : structure Android-only versus multi-plateforme, composition langage/build, matrice AGP/Gradle/JDK, niveaux SDK, identité applicative, versioning, configuration locale et signing.
Cette tranche ne couvre pas encore NDK/ABI/native packaging, APK/AAB, Android Lint, tests instrumentés, installation/smokes device/AVD ni exigences 16 KB ; ces responsabilités restent réservées à `alpha.3`.
## Modifications
### Version
`VERSION` devient :
```text
0.1.3-alpha.2
```
### Plan Android
`docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md` passe en révision interne `2` et enregistre :
- le `PASS` opérateur réel de `alpha.1` ;
- l'absence de fix avant `alpha.2` ;
- les sources Android officielles vérifiées le `2026-09-28` ;
- la confirmation que les valeurs Games AGP `9.4.0`, Gradle `>= 9.6.0` et JDK observé restent des preuves locales et non des minima PGR ;
- le scope exact de `alpha.2` ;
- le maintien du détail 16 KB dans `alpha.3`.
### Profil Android
`docs/rules/610-ANDROID.md` passe en révision interne `4`.
La révision :
- conserve `Android/` comme convention conditionnelle d'un dépôt multi-plateforme, mais retire `gradlew*` du layout d'exemple afin de ne plus présenter le Wrapper comme structure obligatoire ;
- rend le profil Android neutre quant au langage applicatif et applique `520-JAVA.md` uniquement lorsque du Java est réellement présent ;
- distingue le JDK qui exécute Gradle/AGP du niveau Java du code applicatif ;
- conserve la matrice AGP/Gradle/JDK sans recopier les règles générales possédées par `522-GRADLE.md` ;
- clarifie `compileSdk`, `targetSdk` et `minSdk` comme trois contrats distincts ;
- remplace l'objectif implicite « `minSdk` aussi bas que possible » par une décision de compatibilité produit explicitement justifiée ;
- introduit la séparation explicite entre `namespace` et `applicationId` ;
- conserve `VERSION`, `versionName` et `versionCode` comme contrats distincts selon le release train réellement possédé ;
- précise que `local.properties` est réservé à l'environnement local Android/AGP et ne doit pas devenir une source de configuration partagée ou un fourre-tout de propriétés produit ;
- consolide le traitement des keystores, clés et mots de passe de signing sans recopier l'interdiction générale des secrets ;
- clarifie que le manifest possède composants/permissions/capabilities tandis que les identités `namespace` / `applicationId` restent dans la configuration Android du module.
Aucun template, skeleton, audit Python ou contrat de validation Android n'est créé.
## Vérification officielle utilisée
La vérification courante effectuée avant préparation du delta couvre :
```text
Android Gradle plugin 9.4.0 release notes
Configure your build
Java versions in Android builds
Configure the app module
Sign your app
```
Elle confirme notamment la matrice AGP/Gradle/JDK, la distinction du JDK de build et du niveau Java, les responsabilités `compileSdk` / `targetSdk` / `minSdk`, la séparation `namespace` / `applicationId`, le rôle local de `local.properties` et le caractère secret des clés de signing.
Elle n'est pas utilisée pour normaliser encore la contrainte 16 KB.
## 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.3-alpha.2'
git cat-file -e HEAD:history/0.1.3/alpha.1.md
test -f history/0.1.3/alpha.1.md
test -f deltas/0.1.3/alpha.2.md
test ! -e history/0.1.3/alpha.2.md
grep -A2 '^## Statut$' history/0.1.3/alpha.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 2 -->' docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
grep -Fx '<!-- version: 4 -->' docs/rules/610-ANDROID.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.3/alpha.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
android = Path('docs/rules/610-ANDROID.md').read_text(encoding='utf-8')
assert android.startswith('<!-- file: docs/rules/610-ANDROID.md -->\n<!-- version: 4 -->')
for phrase in (
'Android ne sélectionne pas à lui seul le langage applicatif du projet.',
'JDK qui exécute Gradle / AGP',
'Le choix de `minSdk` MUST être justifié par le contrat produit',
'## Identité applicative et namespace',
'`applicationId` identifie l\'application installée et distribuée.',
'`local.properties` appartient à l\'environnement local du build Android/AGP',
'release / upload keystore',
'`AndroidManifest.xml` MUST déclarer uniquement les composants',
):
assert phrase in android, phrase
structure = android.split('## Structure du projet', 1)[1].split('## Langage applicatif et logique de build', 1)[0]
assert 'gradlew' not in structure
assert 'settings.gradle(.kts)' in structure
assert '<module>/' in structure
assert 'Java est le langage applicatif Android par défaut du profil PGR' not in android
assert '`minSdk` SHOULD rester aussi bas que raisonnablement supportable' not in android
plan = Path('docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'## Décision après `alpha.1`',
'La gate opérateur de `alpha.1` est `PASS`',
'### Vérification Android officielle courante pour `alpha.2`',
'AGP `9.4.0` requiert actuellement au minimum Gradle `9.6.0` et JDK `17`',
'La vérification 16 KB n\'est pas absorbée ici',
'### Scope arrêté pour `alpha.2`',
):
assert phrase in plan, phrase
assert not Path('docs/validation/006-ANDROID_VALIDATION.md').exists()
assert not Path('history/0.1.3/alpha.2.md').exists()
for path in (
'docs/rules/520-JAVA.md',
'docs/rules/522-GRADLE.md',
'docs/rules/600-PLATFORMS.md',
):
assert Path(path).is_file(), path
print('0.1.3 alpha.2 Android base-contract audit: clean (language/build ownership, SDK contracts, app identity, local config and signing clarified)')
PYGATE
git diff --check
git add VERSION \
docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md \
docs/rules/610-ANDROID.md \
deltas/0.1.3/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.3/alpha.2.md
M docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
M docs/rules/610-ANDROID.md
```
La revue qualitative doit confirmer que :
- aucun choix Games n'est devenu une règle Android générale par copie de valeur ;
- Android n'impose plus Java par défaut et ne confond pas JDK de build avec niveau Java applicatif ;
- l'exemple structurel ne rend ni Wrapper ni Gradle système obligatoire ;
- `minSdk` est une décision de compatibilité produit et non un concours vers la valeur la plus basse ;
- `namespace` et `applicationId` sont distingués sans imposer un schéma de nommage propriétaire ;
- `local.properties` ne devient pas une configuration partagée et les secrets de signing restent hors Git ;
- aucun contenu NDK/ABI/16 KB, Tauri ou adoption Games n'a été absorbé prématurément ;
- aucun artefact supplémentaire n'a été créé uniquement pour remplir la release.
## Transition
### PASS
Produire `history/0.1.3/alpha.2.md`, puis préparer `0.1.3-alpha.3` pour les responsabilités conditionnelles NDK/ABI/native packaging, APK/AAB, Android Lint, niveaux de tests, install/smokes device/AVD et contraintes de distribution modernes réellement applicables.
Avant toute règle 16 KB, vérifier explicitement les exigences Android officielles courantes et borner le contrat au canal de distribution et aux artefacts natifs réellement concernés.
### FAIL
Consigner le diagnostic réel dans `history/0.1.3/alpha.2.md` et rester dans `alpha.2.fix.N` sauf REPLAN justifié. Le fix MUST rester borné aux contrats Android de base et ne doit pas absorber le scope natif/distribution de `alpha.3`, Tauri `0.1.4` ou l'adoption Games `0.1.5`.

211
deltas/0.1.3/alpha.3.md Normal file
View File

@@ -0,0 +1,211 @@
<!-- file: deltas/0.1.3/alpha.3.md -->
<!-- version: 1 -->
# Delta 0.1.3-alpha.3 — natif, packaging, distribution et validation Android
## Baseline
Ce delta s'applique après :
```text
0.1.3-alpha.2
+ history/0.1.3/alpha.2.md PASS
+ commit/push complet de la tranche alpha.2
```
Il ne doit pas être appliqué avant l'intégration du history `alpha.2`.
## Objet
Réviser le profil Android uniquement sur les responsabilités conditionnelles démontrées par Games et confirmées par la documentation Android officielle courante : NDK/ABI/code natif, Android Lint, niveaux de tests, APK/AAB, installation/smokes device/AVD et compatibilité 16 KB lorsque le package ou le canal de distribution l'exigent réellement.
Cette tranche ne crée aucun owner JNI/Rust/SDL, skeleton Android, audit Python ou contrat `docs/validation/` séparé. Elle ne modifie ni Tauri `0.1.4`, ni Games `0.1.5`.
## Modifications
### Version
`VERSION` devient :
```text
0.1.3-alpha.3
```
### Plan Android
`docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md` passe en révision interne `3` et enregistre :
- le `PASS` opérateur réel de `alpha.2` ;
- l'absence de fix avant `alpha.3` ;
- les sources Android officielles vérifiées le `2026-09-28` pour native/ABI, Lint, tests, packaging, Google Play et 16 KB ;
- le caractère évolutif des exigences de canal telles que `targetSdk` et les échéances de publication ;
- la cohérence de la preuve Games 16 KB sans la transformer en gate PGR locale ;
- le scope exact de `alpha.3` ;
- le maintien de la décision finale d'artefacts supplémentaires dans `beta.1`.
### Profil Android
`docs/rules/610-ANDROID.md` passe en révision interne `5`.
La révision :
- rend NDK et ABI conditionnels à la présence de bibliothèques natives directes ou transitives ;
- refuse toute version NDK ou liste d'ABI universelle et distingue compilation native, présence dans le package et preuve runtime ;
- inclut les SDK/bibliothèques natives précompilés dans le contrat de compatibilité du package final ;
- garde JNI, Rust, SDL, `cargo ndk` et les choix Games hors du profil Android général ;
- introduit une section Android Lint qui impose une exécution explicite et ciblée lorsqu'elle est applicable, sans supposer qu'un build ordinaire l'exécute ;
- précise les frontières JVM unit / instrumented / smoke device-AVD et la sélection proportionnée des matrices ;
- distingue l'APK installable de l'AAB de distribution et interdit d'utiliser un AAB seul comme preuve runtime ;
- impose de revalider les politiques évolutives du canal de distribution au moment de la release concernée ;
- normalise la compatibilité 16 KB uniquement lorsqu'il existe du code natif et qu'elle est requise par la plateforme ou le canal ;
- demande alors une preuve adaptée sur les bibliothèques 64 bits, le package APK/AAB et, lorsque nécessaire, un environnement runtime 16 KB ;
- conserve les versions AGP/NDK et les commandes précises comme moyens de preuve/toolchain, non comme minima PGR génériques.
## Vérification officielle utilisée
La vérification courante effectuée avant préparation du delta couvre :
```text
Support 16 KB page sizes
Android ABIs
Improve your code with lint checks
Test from the command line
Build your app from the command line
Meet Google Play's target API level requirement
```
Elle confirme notamment, au `2026-09-28` :
- Google Play demande depuis le `2026-08-31` API `36+` pour les nouvelles applications et mises à jour Android ordinaires, avec des règles distinctes pour certains form factors ; cette valeur reste une politique Play datée, pas un default Android PGR ;
- les applications Google Play ciblant API `35+` doivent supporter les pages `16 KB` sur appareils 64 bits et la documentation courante annonce le `2027-02-01` comme échéance à partir de laquelle les mises à jour non compatibles ne pourront plus être publiées ;
- une application sans code natif direct ou transitif n'a pas de réalignement ELF à effectuer ; une application native doit vérifier aussi ses bibliothèques tierces précompilées ;
- les moyens officiels de preuve couvrent les segments ELF, `zipalign -P 16` pour l'APK, l'alignement déclaré dans l'AAB via `bundletool` et, lorsque pertinent, un test sur environnement 16 KB ;
- AGP `8.5.1+` et NDK `r28+` facilitent le chemin standard actuel mais ne deviennent pas des minima PGR universels ;
- Lint doit être lancé explicitement ; les tests locaux JVM et instrumentés ont des environnements et des responsabilités distincts ;
- un APK est directement installable, tandis qu'un AAB sert à la distribution et n'est pas une preuve runtime par lui-même.
## Validation opérateur
Après application du history `PASS`, commit/push de `alpha.2`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.3-alpha.3'
git cat-file -e HEAD:history/0.1.3/alpha.2.md
test -f history/0.1.3/alpha.2.md
test -f deltas/0.1.3/alpha.3.md
test ! -e history/0.1.3/alpha.3.md
grep -A2 '^## Statut$' history/0.1.3/alpha.2.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 3 -->' docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
grep -Fx '<!-- version: 5 -->' docs/rules/610-ANDROID.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.3/alpha.2.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
android = Path('docs/rules/610-ANDROID.md').read_text(encoding='utf-8')
assert android.startswith('<!-- file: docs/rules/610-ANDROID.md -->\n<!-- version: 5 -->')
for phrase in (
'## NDK, ABI et code natif',
'bibliothèques natives précompilées ou apportées par un SDK',
'compilation native',
'packaging',
'runtime',
'## Android Lint',
'PGR MUST NOT supposer qu\'un build Gradle ordinaire exécute Lint automatiquement.',
'JVM unit',
'instrumented / integration',
'smoke device / AVD',
'Un AAB n\'est pas directement une preuve d\'installation ou d\'exécution sur device.',
'## Pages mémoire 16 KB et packaging natif',
'Google Play',
'API `35` ou supérieur',
'`zipalign -P 16`',
'`bundletool`',
):
assert phrase in android, phrase
assert 'PGR ne fixe ni version NDK ni liste universelle d\'ABI.' in android
assert 'PGR MUST NOT imposer une version AGP/NDK globale uniquement pour cette raison.' in android
assert 'targetSdk` minimal' in android
plan = Path('docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'## Décision après `alpha.2`',
'La gate opérateur de `alpha.2` est `PASS`',
'### Vérification Android officielle courante pour `alpha.3`',
'depuis le `2026-08-31`',
'à partir du `2027-02-01`',
'### Scope arrêté pour `alpha.3`',
'Aucun owner JNI/Rust/SDL, skeleton Android, audit Python ou contrat `docs/validation/` n\'est créé.',
):
assert phrase in plan, phrase
assert not Path('docs/validation/006-ANDROID_VALIDATION.md').exists()
assert not Path('history/0.1.3/alpha.3.md').exists()
for forbidden in (
'NDK MUST être r28',
'MUST supporter arm64-v8a, armeabi-v7a, x86_64 et x86',
'targetSdk MUST être 36',
):
assert forbidden not in android, forbidden
print('0.1.3 alpha.3 Android native/distribution audit: clean (conditional native ownership, lint/tests/package boundaries and 16 KB policy verified)')
PYGATE
git diff --check
git add VERSION \
docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md \
docs/rules/610-ANDROID.md \
deltas/0.1.3/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.1.3/alpha.3.md
M docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
M docs/rules/610-ANDROID.md
```
La revue qualitative doit confirmer que :
- aucune valeur Games (NDK `r28c`, quatre ABI, SDL3, Rust/JNI) n'est devenue une règle Android générale ;
- une application sans code natif n'hérite d'aucune gate NDK/ABI/ELF artificielle ;
- une dépendance native précompilée est couverte par la même preuve package que le code natif du projet ;
- Android Lint, tests JVM, tests instrumentés, package, install et smoke restent des preuves distinctes et proportionnées ;
- un AAB n'est pas traité comme un artefact directement installable ;
- la règle 16 KB est conditionnelle, fondée sur la politique officielle courante et ne fige ni date ni version d'outil comme default PGR durable ;
- le profil exige de revalider les politiques de distribution évolutives plutôt que de conserver aveuglément une valeur `targetSdk` datée ;
- PGR ne prétend pas avoir reconstruit les APK/AAB Games pendant cette tranche documentaire ;
- aucun contrat Android séparé, skeleton, audit ou owner spécialisé n'a été créé uniquement pour remplir la release ;
- Tauri `0.1.4` et l'adoption Games `0.1.5` restent hors scope.
## Transition
### PASS
Produire `history/0.1.3/alpha.3.md`, puis préparer `0.1.3-beta.1` pour la réconciliation du profil Android révisé contre Games, `520-JAVA.md`, `522-GRADLE.md`, `600-PLATFORMS.md` et `400-VALIDATION.md`.
La beta doit décider explicitement si `610-ANDROID.md` et les owners existants suffisent. Si un artefact fonctionnel supplémentaire devient réellement nécessaire, déclencher un REPLAN vers une tranche alpha dédiée au lieu de l'ajouter en beta.
### FAIL
Consigner le diagnostic réel dans `history/0.1.3/alpha.3.md` et rester dans `alpha.3.fix.N` sauf REPLAN justifié. Le fix MUST rester borné au natif, packaging, distribution et validation Android et ne doit pas absorber Tauri `0.1.4` ou l'adoption Games `0.1.5`.

266
deltas/0.1.3/beta.1.md Normal file
View File

@@ -0,0 +1,266 @@
<!-- file: deltas/0.1.3/beta.1.md -->
<!-- version: 1 -->
# Delta 0.1.3-beta.1 — réconciliation Android et décision finale d'artefacts
## Baseline et version
Baseline attendue : commit opérateur de `0.1.3-alpha.3`, réalisé après application de `history/0.1.3/alpha.3.md` avec statut `PASS`.
Version avant application :
```text
0.1.3-alpha.3
```
Version après application :
```text
0.1.3-beta.1
```
## Objet
Cette tranche exécute la réconciliation prévue après les révisions Android `alpha.2` et `alpha.3`. Elle ne crée aucune nouvelle règle fonctionnelle et ne modifie pas `610-ANDROID.md`.
La beta vérifie que le profil révisé reste générique face au corpus Games, se compose correctement avec `400-VALIDATION.md`, `520-JAVA.md`, `522-GRADLE.md` et `600-PLATFORMS.md`, puis tranche explicitement la question des artefacts Android supplémentaires.
## Scope
REPLACE :
```text
VERSION
README.md
docs/000-README.md
docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
```
ADD :
```text
deltas/0.1.3/beta.1.md
```
DELETE : aucun.
Aucun `history/0.1.3/beta.1.md` n'est anticipé.
## Réconciliation contre les owners PGR
La revue confirme la composition suivante :
```text
400-VALIDATION.md sélection et autorité générales des preuves
520-JAVA.md Java uniquement lorsqu'il est présent
522-GRADLE.md Gradle uniquement lorsqu'il est utilisé
600-PLATFORMS.md contrat commun des plateformes
610-ANDROID.md spécialisation Android
```
Le profil Android ne recopie donc pas les contrats Java/Gradle généraux et ne transforme pas la présence d'AGP ou d'un JDK de build en applicabilité automatique du profil Java.
`400-VALIDATION.md` possède déjà la validation proportionnée et les catégories de preuves. `610-ANDROID.md` ajoute uniquement les responsabilités Android nécessaires pour choisir Lint, tests, packaging, installation et smokes selon le risque.
## Réconciliation contre Games
Les choix réutilisables démontrés par Games sont intégrés comme contrats génériques sans reprendre ses valeurs concrètes.
Restent explicitement locaux à Games :
```text
chemin concret Android/
Groovy DSL
Gradle système sans Wrapper
AGP 9.4.0
Gradle 9.7.1 / contrainte système >= 9.6.0
JDK 25.0.4.1
Java source/target 17
compileSdk 36 / targetSdk 36 / minSdk 21
NDK r28c
arm64-v8a / armeabi-v7a / x86_64 / x86
cargo ndk / bridge JNI / SDL3 / staging jniLibs
modules, Activities, labels et assets Games
```
Aucune de ces valeurs n'est promue comme minimum Android PGR.
Les deux corrections `OVERRIDE` initiales sont résolues : le Wrapper n'est plus présenté comme élément structurel obligatoire et `minSdk` est un contrat produit explicitement justifié.
Le sujet 16 KB, initialement `DEFER`, a été vérifié pendant `alpha.3` puis normalisé uniquement de manière conditionnelle au code natif, au package et au canal de distribution concerné. Les versions d'outils et échéances observées restent des informations datées, pas des defaults universels.
## Décision finale d'artefacts
Aucun artefact technique supplémentaire n'est justifié pour `0.1.3`.
Ne sont donc pas créés :
```text
docs/validation/006-ANDROID_VALIDATION.md
skeleton Android
template de build Android générique
audit Python Android
owner JNI / Rust Android / SDL
```
`400 + 600 + 610`, complétés par `520` et `522` lorsqu'ils sont applicables, couvrent déjà les responsabilités réutilisables démontrées. PGR ne possède en outre aucun build Android exécutable qui fournirait aujourd'hui un sujet légitime pour un skeleton, template ou audit spécialisé.
Si un nouvel artefact fonctionnel devenait réellement nécessaire, il exigerait un REPLAN vers une tranche alpha dédiée. La beta ne doit pas ajouter opportunément du contenu fonctionnel nouveau.
## Documentation durable
La tranche actualise :
- le statut racine de la release ;
- l'index documentaire `0.1.3` ;
- le plan actif avec le `PASS` réel de `alpha.3`, la résolution des classifications et la décision finale d'artefacts.
`610-ANDROID.md` reste en révision `5`. `ROADMAP.md`, `CHANGELOG.md`, `RULES.md`, les owners `400/520/522/600`, les skeletons, templates, validations et scripts restent inchangés.
Tauri demeure strictement réservé à `0.1.4` et l'adoption Games à `0.1.5`.
## Validation opérateur
Après application du history `PASS` de `alpha.3`, commit/push de `alpha.3`, puis application du présent delta :
```bash
test "$(cat VERSION)" = '0.1.3-beta.1'
git cat-file -e HEAD:history/0.1.3/alpha.3.md
test -f history/0.1.3/alpha.3.md
test -f deltas/0.1.3/beta.1.md
test ! -e history/0.1.3/beta.1.md
grep -A2 '^## Statut$' history/0.1.3/alpha.3.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 24 -->' README.md
grep -Fx '<!-- version: 38 -->' docs/000-README.md
grep -Fx '<!-- version: 4 -->' docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
grep -Fx '<!-- version: 5 -->' docs/rules/610-ANDROID.md
grep -Fx '<!-- version: 1 -->' docs/rules/400-VALIDATION.md
grep -Fx '<!-- version: 4 -->' docs/rules/520-JAVA.md
grep -Fx '<!-- version: 1 -->' docs/rules/522-GRADLE.md
grep -Fx '<!-- version: 1 -->' docs/rules/600-PLATFORMS.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.3/alpha.3.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS\s', history)
validation = Path('docs/rules/400-VALIDATION.md').read_text(encoding='utf-8')
java = Path('docs/rules/520-JAVA.md').read_text(encoding='utf-8')
gradle = Path('docs/rules/522-GRADLE.md').read_text(encoding='utf-8')
platforms = Path('docs/rules/600-PLATFORMS.md').read_text(encoding='utf-8')
android = Path('docs/rules/610-ANDROID.md').read_text(encoding='utf-8')
plan = Path('docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'La validation existe pour fournir une preuve utile proportionnée au changement.',
'BUILD, PACKAGE et PUBLISH',
'## Autorité du gate opérateur',
):
assert phrase in validation, phrase
assert '# Profil Java' in java
assert '# Profil Gradle' in gradle
assert '# Règles de profils plateforme' in platforms
for phrase in (
'Android ne sélectionne pas à lui seul le langage applicatif du projet.',
'Le choix de `minSdk` MUST être justifié par le contrat produit',
'PGR ne fixe ni version NDK ni liste universelle d\'ABI.',
'PGR MUST NOT supposer qu\'un build Gradle ordinaire exécute Lint automatiquement.',
'Un AAB n\'est pas directement une preuve d\'installation ou d\'exécution sur device.',
'## Pages mémoire 16 KB et packaging natif',
'PGR MUST NOT imposer une version AGP/NDK globale uniquement pour cette raison.',
):
assert phrase in android, phrase
for forbidden in (
'targetSdk MUST être 36',
'minSdk MUST être 21',
'NDK MUST être r28',
'MUST supporter arm64-v8a, armeabi-v7a, x86_64 et x86',
'Gradle MUST être 9.7.1',
'AGP MUST être 9.4.0',
'JDK MUST être 25',
):
assert forbidden not in android, forbidden
for phrase in (
'## Décision après `alpha.3` et réconciliation `beta.1`',
'La gate opérateur de `alpha.3` est `PASS`',
'### Résolution de la classification initiale',
'### Décision finale d\'artefacts Android',
'Aucun artefact technique supplémentaire n\'est justifié pour `0.1.3`.',
'docs/validation/006-ANDROID_VALIDATION.md',
'### Frontières après réconciliation',
'Tauri 0.1.4',
'adoption Games 0.1.5',
):
assert phrase in plan, phrase
assert not Path('docs/validation/006-ANDROID_VALIDATION.md').exists()
assert not Path('history/0.1.3/beta.1.md').exists()
for forbidden_path in (
'templates/android',
'docs/skeletons/004-ANDROID.md',
'docs/rules/620-JNI.md',
):
assert not Path(forbidden_path).exists(), forbidden_path
print('0.1.3 beta.1 reconciliation audit: clean (Android profile generic, Games-local choices preserved, existing owners sufficient, no extra artifacts justified)')
PYGATE
git diff --check
git add README.md VERSION \
docs/000-README.md \
docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md \
deltas/0.1.3/beta.1.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est exactement :
```text
M README.md
M VERSION
A deltas/0.1.3/beta.1.md
M docs/000-README.md
M docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
```
La revue qualitative doit confirmer que :
- aucun choix local Games n'est devenu une règle Android générale ;
- les contraintes NDK/ABI/16 KB restent conditionnelles et n'imposent aucune toolchain universelle ;
- Java et Gradle restent des profils composés uniquement lorsqu'ils sont applicables ;
- `400 + 600 + 610` expriment déjà la validation Android sans contrat séparé redondant ;
- aucun skeleton, template, audit ou owner spécialisé n'est ajouté pour satisfaire une structure théorique ;
- Tauri `0.1.4` n'est pas commencé et l'adoption Games `0.1.5` reste hors scope ;
- aucun `0.1.8` n'est réservé.
## Transition
### PASS
Produire `history/0.1.3/beta.1.md`, puis préparer `0.1.3-rc.1` pour geler le scope Android, préparer le changelog candidat et le prompt de reprise `0.1.4`, puis rejouer le release gate complet sans commencer Tauri.
### FAIL
Consigner le diagnostic réel dans `history/0.1.3/beta.1.md`, puis produire `beta.1.fix.N` ou effectuer un REPLAN uniquement si un défaut d'ownership, de généricité ou de frontière ne peut pas être corrigé localement sans nouvelle matière fonctionnelle.

312
deltas/0.1.3/rc.1.md Normal file
View File

@@ -0,0 +1,312 @@
<!-- file: deltas/0.1.3/rc.1.md -->
<!-- version: 1 -->
# Delta 0.1.3-rc.1 — gel du scope Android et gate de release candidate
## Baseline et version
Baseline attendue : commit opérateur de `0.1.3-beta.1`, réalisé après application de `history/0.1.3/beta.1.md` avec statut `PASS`.
Le hash de ce commit n'est pas anticipé.
Version avant application :
```text
0.1.3-beta.1
```
Version après application :
```text
0.1.3-rc.1
```
## Objet et gel
La RC gèle le scope fonctionnel de `0.1.3` sur :
- Android comme spécialisation de `600-PLATFORMS.md`, neutre vis-à-vis du langage applicatif et composant Java/Gradle uniquement lorsqu'ils sont réellement applicables ;
- les responsabilités distinctes de `compileSdk`, `targetSdk` et `minSdk`, avec `minSdk` justifié par le contrat produit plutôt que minimisé cérémoniellement ;
- `namespace`, `applicationId`, manifests/resources, configuration locale et signing comme responsabilités Android clairement bornées ;
- NDK, ABI et bibliothèques natives uniquement pour les projets réellement concernés, sans version NDK ni liste d'ABI universelles ;
- la séparation entre compilation native, packaging et preuve runtime ;
- Android Lint comme gate explicite, avec tests JVM, tests instrumentés et smokes device/AVD sélectionnés proportionnellement au changement ;
- la distinction APK/AAB versus preuve d'installation/exécution ;
- la compatibilité pages mémoire 16 KB comme contrat conditionnel au code natif, au package et au canal de distribution concernés, sans minimum AGP/NDK/SDK universel ;
- les choix spécifiques Games — versions d'outils, niveaux SDK, quatre ABI, Rust/JNI/SDL, modules et assets — conservés comme décisions locales ;
- la décision beta qu'aucun skeleton Android, template de build, audit Python, owner JNI/Rust/SDL ni contrat de validation Android séparé n'est justifié ;
- la frontière suivante : réexamen Tauri `0.1.4`, adoption Games `0.1.5`, adoption KSP `0.1.6`.
Le changelog reçoit une entrée candidate `0.1.3` orientée utilisateurs. Le prompt `010-V0_1_4_START_PROMPT.md` est préparé pour le réexamen Tauri après publication vérifiée de `v0.1.3`.
Aucune nouvelle règle fonctionnelle Android n'entre dans cette RC. Les owners, skeletons, templates, validations et scripts sont vérifiés mais non modifiés.
## Scope
REPLACE :
```text
VERSION
CHANGELOG.md
docs/000-README.md
docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
```
ADD :
```text
deltas/0.1.3/rc.1.md
prompts/010-V0_1_4_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.3-rc.1'
git cat-file -e HEAD:history/0.1.3/beta.1.md
test -f history/0.1.3/beta.1.md
test -f deltas/0.1.3/rc.1.md
test -f prompts/010-V0_1_4_START_PROMPT.md
test ! -e history/0.1.3/rc.1.md
grep -A2 '^## Statut$' history/0.1.3/beta.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 16 -->' CHANGELOG.md
grep -Fx '## 0.1.3 (candidate)' CHANGELOG.md
grep -Fx '<!-- version: 39 -->' docs/000-README.md
grep -Fx '<!-- version: 5 -->' docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
grep -Fx '<!-- version: 14 -->' ROADMAP.md
grep -Fx '<!-- version: 1 -->' prompts/010-V0_1_4_START_PROMPT.md
grep -Fx '<!-- version: 5 -->' docs/rules/610-ANDROID.md
grep -Fx '<!-- version: 6 -->' docs/rules/710-TAURI.md
grep -Fx '<!-- version: 2 -->' docs/studies/002-TAURI_SKELETON_DECISION.md
grep -Fx '<!-- version: 1 -->' docs/skeletons/003-WEB_FRONTEND.md
grep -Fx '<!-- version: 1 -->' docs/validation/005-WEB_FRONTEND_VALIDATION.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": "PASS",
"alpha.3.md": "PASS",
"beta.1.md": "PASS",
}
histories = {path.name for path in Path("history/0.1.3").glob("*.md")}
assert histories == set(expected), histories
for name, status in expected.items():
text = Path("history/0.1.3", 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.3").glob("*.md")}
assert deltas == set(expected) | {"rc.1.md"}, deltas
changelog = Path("CHANGELOG.md").read_text(encoding="utf-8")
assert "## 0.1.3 (candidate)" in changelog
section = changelog.split("## 0.1.3 (candidate)", 1)[1].split("## 0.1.2", 1)[0]
for phrase in (
"profil Android",
"compileSdk",
"targetSdk",
"minSdk",
"namespace",
"applicationId",
"NDK",
"Android Lint",
"tests instrumentés",
"APK/AAB",
"16 KB",
"0.1.4",
"0.1.5",
):
assert phrase in section, phrase
for forbidden in (
"alpha.1",
"alpha.2",
"alpha.3",
"beta.1",
"rc.1",
):
assert forbidden not in section, forbidden
android = Path("docs/rules/610-ANDROID.md").read_text(encoding="utf-8")
for phrase in (
"Android ne sélectionne pas à lui seul le langage applicatif du projet.",
"Le choix de `minSdk` MUST être justifié par le contrat produit",
"PGR ne fixe ni version NDK ni liste universelle d'ABI.",
"PGR MUST NOT supposer qu'un build Gradle ordinaire exécute Lint automatiquement.",
"Un AAB n'est pas directement une preuve d'installation ou d'exécution sur device.",
"## Pages mémoire 16 KB et packaging natif",
"PGR MUST NOT imposer une version AGP/NDK globale uniquement pour cette raison.",
):
assert phrase in android, phrase
for forbidden in (
"targetSdk MUST être 36",
"minSdk MUST être 21",
"NDK MUST être r28",
"MUST supporter arm64-v8a, armeabi-v7a, x86_64 et x86",
"Gradle MUST être 9.7.1",
"AGP MUST être 9.4.0",
"JDK MUST être 25",
):
assert forbidden not in android, forbidden
plan = Path("docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md").read_text(encoding="utf-8")
for phrase in (
"### beta.1 — réconciliation et décision d'artefacts\n\nRelire",
"Statut opérateur : **PASS**.",
"### rc.1 — release candidate\n\nStatut opérateur : **à valider**.",
"prompts/010-V0_1_4_START_PROMPT.md",
"Aucune nouvelle fonctionnalité normative Android ne doit apparaître en RC.",
):
assert phrase in plan, phrase
prompt = Path("prompts/010-V0_1_4_START_PROMPT.md").read_text(encoding="utf-8")
for phrase in (
"archive source téléchargée depuis le tag Gitea `v0.1.3`",
"pgr-0.1.3-publish.001-report.md",
"0.1.4-alpha.1",
"2a9cabcb9f147a348dcf8d24df8bc6c5029089b6d49feb17bd4a42b4293c329a",
"ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8",
"002-TAURI_SKELETON_DECISION.md",
"710-TAURI.md",
"003-WEB_FRONTEND",
"ADOPT / KEEP-LOCAL / OVERRIDE / DEFER",
"conditions de sortie",
"créer le skeleton Tauri parce que la roadmap le mentionne",
"adoption Games `0.1.5`",
"adoption KSP `0.1.6`",
):
assert phrase in prompt, phrase
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",
"création automatique interdite",
):
assert phrase in study, phrase
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
for version in ("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 forbidden_path in (
"docs/validation/006-ANDROID_VALIDATION.md",
"docs/skeletons/004-ANDROID.md",
"docs/rules/620-JNI.md",
"docs/skeletons/004-TAURI.md",
):
assert not Path(forbidden_path).exists(), forbidden_path
index = Path("docs/000-README.md").read_text(encoding="utf-8")
assert "../prompts/010-V0_1_4_START_PROMPT.md" in index
print("0.1.3 rc.1 integration audit: clean (4 prior histories, frozen Android profile, candidate changelog and prompt 010 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/templates sans simuler une toolchain Android ou Tauri absente du dépôt PGR :
```bash
python3 -B - <<'PYHYGIENE'
from pathlib import Path
import json
import tomllib
for path in sorted(Path("templates/rust-cargo").rglob("*.toml")):
tomllib.loads(path.read_text(encoding="utf-8"))
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.3 rc.1 text/template hygiene: clean")
PYHYGIENE
git diff --check
git add VERSION CHANGELOG.md docs/000-README.md \
docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md \
deltas/0.1.3/rc.1.md prompts/010-V0_1_4_START_PROMPT.md
git diff --cached --check
git status --short
```
Le scope indexé attendu avant ajout du history est exactement :
```text
M CHANGELOG.md
M VERSION
A deltas/0.1.3/rc.1.md
M docs/000-README.md
M docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
A prompts/010-V0_1_4_START_PROMPT.md
```
La revue qualitative doit confirmer que :
- aucune règle fonctionnelle Android nouvelle n'entre en RC ;
- `610-ANDROID.md` reste en révision `5` et aucun choix Games n'est généralisé ;
- aucun artefact Android supplémentaire n'est créé ;
- le changelog candidat décrit la valeur utilisateur de `0.1.3` sans recopier la chronologie alpha/beta/RC ;
- le prompt `010` exige une future stable `v0.1.3` réellement publiée et son rapport post-tag `PASS` ;
- le `DEFER` Tauri n'est pas levé par le prompt : `0.1.4` doit le réexaminer objectivement contre les corpus courants ;
- l'adoption Games `0.1.5` et l'adoption KSP `0.1.6` ne sont pas commencées ;
- aucune preuve Android/Tauri exécutable n'est simulée dans PGR.
## Transition
### PASS
Produire séparément `history/0.1.3/rc.1.md`, puis préparer la promotion mécanique `0.1.3-rel.1` sans rouvrir le scope fonctionnel.

288
deltas/0.1.3/rel.1.md Normal file
View File

@@ -0,0 +1,288 @@
<!-- file: deltas/0.1.3/rel.1.md -->
<!-- version: 1 -->
# Delta 0.1.3 rel.1 — promotion stable pré-tag
## Baseline et version
Baseline : `0.1.3-rc.1`, avec `history/0.1.3/rc.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.1.3-rc.1
```
Version après application :
```text
0.1.3
```
`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.3` 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 `009` historique. Aucun owner Android/Java/Gradle/Tauri, template, skeleton, validation, étude technique ou script d'audit n'est modifié.
La validation de cette tranche est **pré-tag**. Le tag `v0.1.3`, son archive source Gitea et le rapport `pgr-0.1.3-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.3` et la publication réelle du tag.
## Scope
REPLACE :
```text
VERSION
README.md
ROADMAP.md
CHANGELOG.md
docs/000-README.md
docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
```
ADD :
```text
deltas/0.1.3/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.3/rc.1.md` :
```bash
test "$(cat VERSION)" = '0.1.3'
git cat-file -e HEAD:history/0.1.3/rc.1.md
test -f history/0.1.3/rc.1.md
test -f deltas/0.1.3/rel.1.md
test -f prompts/010-V0_1_4_START_PROMPT.md
test ! -e history/0.1.3/rel.1.md
grep -A2 '^## Statut$' history/0.1.3/rc.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 25 -->' README.md
grep -Fx '<!-- version: 15 -->' ROADMAP.md
grep -Fx '<!-- version: 17 -->' CHANGELOG.md
grep -Fx '<!-- version: 40 -->' docs/000-README.md
grep -Fx '<!-- version: 6 -->' docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
grep -F -- '- `(x) 0.1.3`' ROADMAP.md
grep -Fx '## 0.1.3' CHANGELOG.md
grep -F 'avec `0.1.3` d’un profil Android réévalué contre Games' README.md
grep -F 'plan historique de la stable `0.1.3`' docs/000-README.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
expected = {
"alpha.1.md": "PASS",
"alpha.2.md": "PASS",
"alpha.3.md": "PASS",
"beta.1.md": "PASS",
"rc.1.md": "PASS",
}
for name, status in expected.items():
delta = Path("deltas/0.1.3", name)
history = Path("history/0.1.3", 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.3").glob("*.md")} - {
path.name for path in Path("history/0.1.3").glob("*.md")
}
assert pending == {"rel.1.md"}, pending
roadmap = Path("ROADMAP.md").read_text(encoding="utf-8")
assert "- `(x) 0.1.3`" in roadmap
for version in ("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.3" in changelog.splitlines()
assert "## 0.1.3 (candidate)" not in changelog
section = changelog.split("## 0.1.3", 1)[1].split("## 0.1.2", 1)[0]
for phrase in (
"profil Android",
"compileSdk",
"targetSdk",
"minSdk",
"namespace",
"applicationId",
"NDK",
"Android Lint",
"tests instrumentés",
"APK/AAB",
"16 KB",
"0.1.4",
"0.1.5",
):
assert phrase in section, phrase
for forbidden in ("alpha.1", "alpha.2", "alpha.3", "beta.1", "rc.1", "rel.1"):
assert forbidden not in section, forbidden
readme = Path("README.md").read_text(encoding="utf-8")
assert "avec `0.1.3` d’un profil Android réévalué contre Games" in readme
assert "plan historique de la stable Android `0.1.3`" in readme
index = Path("docs/000-README.md").read_text(encoding="utf-8")
assert "plan historique de la stable `0.1.3`" in index
assert "à exécuter uniquement après publication et vérification post-tag de `v0.1.3`" in index
plan = Path("docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md").read_text(encoding="utf-8")
assert "Plan 0.1.3 — réévaluation pratique Android" in plan
assert "### rc.1 — release candidate\n\nStatut opérateur : **PASS**." in plan
assert "history/0.1.3/rel.1.md" in plan
assert "pgr-0.1.3-publish.001-report.md" in plan
assert "commit `0.1.3` avant le tag `v0.1.3`" in plan
assert "plan historique de la stable `0.1.3`" in plan
prompt = Path("prompts/010-V0_1_4_START_PROMPT.md").read_text(encoding="utf-8")
for phrase in (
"tag Gitea `v0.1.3`",
"pgr-0.1.3-publish.001-report.md",
"0.1.4-alpha.1",
"002-TAURI_SKELETON_DECISION.md",
"710-TAURI.md",
"003-WEB_FRONTEND",
"ADOPT / KEEP-LOCAL / OVERRIDE / DEFER",
"adoption Games `0.1.5`",
"adoption KSP `0.1.6`",
):
assert phrase in prompt, phrase
for path, version in (
("docs/rules/400-VALIDATION.md", 1),
("docs/rules/520-JAVA.md", 4),
("docs/rules/522-GRADLE.md", 1),
("docs/rules/600-PLATFORMS.md", 1),
("docs/rules/610-ANDROID.md", 5),
("docs/rules/710-TAURI.md", 6),
("docs/studies/002-TAURI_SKELETON_DECISION.md", 2),
("docs/skeletons/003-WEB_FRONTEND.md", 1),
("docs/validation/005-WEB_FRONTEND_VALIDATION.md", 1),
):
lines = Path(path).read_text(encoding="utf-8").splitlines()
assert lines[1] == f"<!-- version: {version} -->", (path, lines[1])
android = Path("docs/rules/610-ANDROID.md").read_text(encoding="utf-8")
for phrase in (
"Android ne sélectionne pas à lui seul le langage applicatif du projet.",
"Le choix de `minSdk` MUST être justifié par le contrat produit",
"PGR ne fixe ni version NDK ni liste universelle d'ABI.",
"PGR MUST NOT supposer qu'un build Gradle ordinaire exécute Lint automatiquement.",
"Un AAB n'est pas directement une preuve d'installation ou d'exécution sur device.",
"## Pages mémoire 16 KB et packaging natif",
"PGR MUST NOT imposer une version AGP/NDK globale uniquement pour cette raison.",
):
assert phrase in android, phrase
for forbidden in (
"targetSdk MUST être 36",
"minSdk MUST être 21",
"NDK MUST être r28",
"MUST supporter arm64-v8a, armeabi-v7a, x86_64 et x86",
"Gradle MUST être 9.7.1",
"AGP MUST être 9.4.0",
"JDK MUST être 25",
):
assert forbidden not in android, forbidden
for forbidden_path in (
"docs/validation/006-ANDROID_VALIDATION.md",
"docs/skeletons/004-ANDROID.md",
"docs/rules/620-JNI.md",
"docs/skeletons/004-TAURI.md",
):
assert not Path(forbidden_path).exists(), forbidden_path
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.3 rel.1 stable gate audit: clean (5 prior histories, rel.1 pending, stable Android presentation and post-tag Tauri 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
import tomllib
for path in sorted(Path("templates/rust-cargo").rglob("*.toml")):
tomllib.loads(path.read_text(encoding="utf-8"))
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.3 rel.1 text/template hygiene: clean")
PYHYGIENE
git diff --check
git add VERSION README.md ROADMAP.md CHANGELOG.md docs/000-README.md \
docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md \
deltas/0.1.3/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.3/rel.1.md
M docs/000-README.md
M docs/plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md
```
La RC a déjà reconfirmé le profil Android gelé, les frontières Tauri/Games/KSP, le contrat du prompt `010` et l'absence d'artefacts Android supplémentaires. Comme `rel.1` ne modifie aucun artefact technique, la promotion stable rejoue les tests PGR, les audits documentaires et l'hygiène des templates sans simuler une toolchain Android absente du dépôt.
## Revue opérateur complémentaire
Confirmer que :
- `0.1.3` est bien présenté comme stable partout où la RC était auparavant candidate ;
- aucun changement fonctionnel Android n'est entré dans `rel.1` ;
- `0.1.4` reste le réexamen Tauri, sans création anticipée du skeleton ;
- `0.1.5` et `0.1.6` restent respectivement les adoptions Games et KSP ;
- le tag et le rapport post-tag ne sont pas anticipés dans le dépôt pré-tag.

207
deltas/0.1.4/alpha.1.md Normal file
View File

@@ -0,0 +1,207 @@
<!-- file: deltas/0.1.4/alpha.1.md -->
<!-- version: 1 -->
# Delta 0.1.4-alpha.1 — intake et cadrage du réexamen Tauri
## Objet
Ouvrir `0.1.4` conformément à `prompts/010-V0_1_4_START_PROMPT.md`, conserver une preuve locale de l'audit des baselines réellement fournies et matérialiser le plan avant toute modification normative ou création d'un skeleton Tauri.
La tranche ne crée pas `docs/skeletons/004-TAURI.md`, ne modifie pas `710-TAURI.md` et ne commence aucune adoption Games/KSP.
## Sources vérifiées avant préparation
```text
pgr-v0.1.3(1).zip
SHA-256 f3a7dffd5fe0fd3542e6b5207fda0b94bca2bd05bd5a54542d0a08d635a5d6ee
CRC PASS
pgr-0.1.3-publish.001-report.md
SHA-256 5405a1d6c216a5882c4638c07d573d50d440ce9e4e892d97f425e99054245544
status PASS
games-v0.3.6(3).zip
SHA-256 ad6e44a1332eb7d6069cf1189d9433f0fbb8fac19c5aac9f4641ac45c1c556e8
CRC PASS
khadhroony-solana-project-v0.3.19(1).zip
SHA-256 64a3813620925fa4f8914cdf74113399cfdd78ad51d60bbeff9bafbddcf4b253
CRC PASS
```
La baseline PGR correspond exactement au SHA canonique publié. La baseline Games correspond exactement à la référence `0.3.6` du prompt. KSP `0.3.19` est le corpus courant explicitement fourni et remplace, pour cette étude, la référence historique `0.3.17` sans prétendre posséder une preuve post-tag non fournie.
## Résultats d'intake
La stable PGR rejoue `48/48` tests Python et ses trois audits Markdown propres.
Games `0.3.6` rejoue ses audits Rust/workspace, Markdown tables et distribution layout propres. KSP `0.3.19` rejoue ses audits Rust/workspace et Markdown tables propres.
L'inventaire Tauri courant comporte `7` hosts : un sous Games et six sous KSP. Les sept convergent sur un host Cargo direct, `build.rs`, `tauri.conf.json`, `capabilities/`, `src/tauri.rs`, `frontend/`, TypeScript et Vite, sans `src-tauri/`.
Les choix Bootstrap/Sass/TS-RS, plugins, windows, ACL, ports, identifiers, bundle/resources et WASM ne convergent pas suffisamment pour devenir des obligations générales.
La relecture des owners Web confirme les cinq conditions historiques de sortie du `DEFER`. La vérification Tauri 2 officielle confirme que le layout standard et les commandes de commodité restent des possibilités supportées, tandis que capabilities/permissions doivent être traitées comme une surface de sécurité explicite.
## Modifications de la tranche
- `VERSION` passe à `0.1.4-alpha.1` ;
- `README.md` annonce l'ouverture du réexamen Tauri et référence son plan actif ;
- `docs/000-README.md` ajoute les points d'entrée actifs de `0.1.4` ;
- `docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md` consigne audits, inventaire, classification et trajectoire ;
- le présent delta conserve le contrat de gate opérateur.
`ROADMAP.md` et `CHANGELOG.md` restent inchangés pendant cette tranche d'ouverture. Leur mise à jour est volontairement réservée aux phases de fermeture lorsque l'état réellement atteint est connu.
## Décision de tranche
```text
conditions Web historiques SATISFIED
ancien motif Web du DEFER LIFT
skeleton Tauri organisationnel ADOPT FOR MATERIALIZATION
création pendant alpha.1 NO
prochaine tranche alpha.2 — réconciliation normative 710 + étude 002
```
Cette décision autorise la matérialisation future du candidat ; elle ne présume pas que sa forme historique est correcte en bloc.
## Gate opérateur
Appliquer le delta puis exécuter depuis la racine du dépôt :
```bash
cat VERSION
test -f docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
test -f deltas/0.1.4/alpha.1.md
test ! -e history/0.1.4/alpha.1.md
test ! -e docs/skeletons/004-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
assert Path('VERSION').read_text(encoding='utf-8').strip() == '0.1.4-alpha.1'
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,
'0.1.1': 11,
'0.1.2': 7,
'0.1.3': 6,
}
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.3').glob('*.md'):
text = path.read_text(encoding='utf-8')
match = re.search(r'## Statut\s+(?:`?)(PASS|FAIL|PARTIAL|BLOCKED)', text)
assert match is not None, path
statuses[path.name] = match.group(1)
assert len(statuses) == 6, statuses
assert set(statuses.values()) == {'PASS'}, statuses
assert statuses['rel.1.md'] == 'PASS'
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
assert '- `(x) 0.1.3`' in roadmap
for release in range(4, 8):
assert f'- `( ) 0.1.{release}`' in roadmap, release
assert '0.1.8' not in roadmap
prompt = Path('prompts/010-V0_1_4_START_PROMPT.md').read_text(encoding='utf-8')
for phrase in (
'Version cible : `0.1.4`',
'Première tranche attendue : `0.1.4-alpha.1`',
'ADOPT / KEEP-LOCAL / OVERRIDE / DEFER',
'conditions de sortie du report historique',
'skeleton Tauri',
'adoption Games `0.1.5`',
'adoption KSP `0.1.6`',
):
assert phrase in prompt, phrase
plan = Path('docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'7` hosts',
'conditions historiques de sortie SATISFIED',
'Classification initiale `alpha.1`',
'### `ADOPT`',
'### `KEEP-LOCAL`',
'### `OVERRIDE`',
'### `DEFER`',
'ADOPT FOR MATERIALIZATION',
'`alpha.2` — réconciliation normative Tauri',
'`alpha.3` — skeleton Tauri contrôlé',
'`beta.1` — réconciliation et décision d\'artefacts',
'`rc.1` — freeze et handoff',
'`rel.1` — stable',
'0.1.5',
'0.1.6',
):
assert phrase in plan, phrase
assert Path('docs/rules/710-TAURI.md').read_text(encoding='utf-8').startswith(
'<!-- file: docs/rules/710-TAURI.md -->\n<!-- version: 6 -->'
)
assert Path('docs/studies/002-TAURI_SKELETON_DECISION.md').read_text(encoding='utf-8').startswith(
'<!-- file: docs/studies/002-TAURI_SKELETON_DECISION.md -->\n<!-- version: 2 -->'
)
assert Path('docs/skeletons/003-WEB_FRONTEND.md').exists()
assert not Path('docs/skeletons/004-TAURI.md').exists()
assert not Path('history/0.1.4/alpha.1.md').exists()
print('0.1.4 alpha.1 structural audit: clean (96 prior pairs, 7 current Tauri hosts classified, no premature skeleton/adoption)')
PY
git diff --check
git add VERSION README.md docs/000-README.md \
docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md \
deltas/0.1.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.1.4/alpha.1.md
M docs/000-README.md
A docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
```
## Revue opérateur attendue
La revue doit confirmer que `alpha.1` ne modifie ni `710-TAURI.md` ni l'étude historique avant validation du cadrage ; que les sept hosts réellement fournis sont utilisés comme preuves et non comme modèles à recopier ; que Bootstrap/Sass/TS-RS/WASM/plugins/windows/ports/identifiers restent correctement classifiés ; et que ni Games ni KSP ne sont adoptés pendant `0.1.4`.
Elle doit aussi confirmer que le candidat de skeleton est **autorisé à être matérialisé plus tard**, et non déjà créé par cette tranche.
## Transition
### PASS
Produire `history/0.1.4/alpha.1.md` à partir des résultats réellement observés. Dans la même réponse, préparer séparément le delta `0.1.4-alpha.2` consacré à la réconciliation normative de `710-TAURI.md` et de `002-TAURI_SKELETON_DECISION.md`, sans créer encore `004-TAURI.md`.
Après remise du history, fournir automatiquement le bloc opérateur exact pour appliquer le history, committer/pusher `0.1.4-alpha.1`, puis seulement appliquer le delta suivant conformément à `docs/templates/006-OPERATOR_COMMAND_HANDOFF.md`.
### FAIL
Consigner le résultat réel dans le history, puis ouvrir `0.1.4-alpha.1.fix.1` ou un REPLAN selon la cause. Aucun changement prévu pour `alpha.2` ne doit être absorbé silencieusement dans le fix.

View File

@@ -0,0 +1,209 @@
<!-- file: deltas/0.1.4/alpha.2.fix.1.md -->
<!-- version: 1 -->
# Delta 0.1.4-alpha.2.fix.1 — hygiène EOF et prévention automatique
## Diagnostic
La gate opérateur de `0.1.4-alpha.2` a validé les `48/48` tests Python, les trois audits Markdown et le contrôle normatif Tauri, puis a échoué sur les deux contrôles Git d'hygiène :
```text
docs/studies/002-TAURI_SKELETON_DECISION.md:299: new blank line at EOF.
```
Le même défaut a été signalé par :
```text
git diff --check
git diff --cached --check
```
`history/0.1.4/alpha.2.md` enregistre donc `FAIL`. Le contenu normatif Tauri de `alpha.2` reste conservé ; le présent fix corrige uniquement l'hygiène mécanique et la lacune de prévention qui a permis la réapparition d'un défaut déjà rencontré historiquement.
Version après application :
```text
0.1.4-alpha.2.fix.1
```
## Objet
Corriger la ligne vide surnuméraire à EOF de l'étude Tauri et faire de cette classe de défaut une propriété automatiquement contrôlée avant les futures livraisons PGR.
Le correctif introduit un audit monotâche read-only au lieu d'ajouter une vérification ad hoc dans chaque delta.
## Scope
REPLACE :
```text
VERSION
docs/rules/210-WORKFLOW.md
docs/studies/002-TAURI_SKELETON_DECISION.md
docs/validation/001-VALIDATION_MATRIX.md
```
ADD :
```text
deltas/0.1.4/alpha.2.fix.1.md
scripts/audit_text_hygiene.py
tests/test_text_hygiene.py
```
Les autres décisions de `alpha.2`, notamment `docs/rules/710-TAURI.md`, le plan `010` et `docs/000-README.md`, MUST rester inchangées.
## Correction EOF
`docs/studies/002-TAURI_SKELETON_DECISION.md` conserve son contenu et sa révision interne `3`. La seule modification de ce fichier est mécanique : sa terminaison passe de deux caractères LF successifs à exactement un LF final.
Aucune décision Tauri n'est modifiée par cette correction.
## Audit `text_hygiene`
`scripts/audit_text_hygiene.py` possède quatre propriétés mécaniques sur les fichiers texte sélectionnés :
```text
LF uniquement
aucun whitespace terminal
newline finale obligatoire
exactement une newline finale, donc aucune ligne vide supplémentaire à EOF
```
L'audit reste read-only, accepte des fichiers ou répertoires explicites et ignore les répertoires générés usuels. Il ne remplace pas un formatter, un parser Markdown ou `git diff --check`.
`tests/test_text_hygiene.py` couvre au minimum :
- fichier propre avec exactement un LF final ;
- ligne vide supplémentaire à EOF ;
- newline finale absente ;
- CRLF ;
- espace ou tabulation terminale ;
- exclusion d'un répertoire généré ;
- sélection invalide.
## Contrat de workflow
`docs/rules/210-WORKFLOW.md` passe de la révision `7` à `8` et rend explicite que le générateur doit contrôler l'hygiène mécanique avant livraison, plutôt que déléguer sa découverte à la gate opérateur.
`docs/validation/001-VALIDATION_MATRIX.md` passe de la révision `14` à `15` et ajoute `PGR-TEXT-HYGIENE-001` comme audit faible coût déclenché lorsqu'un fichier texte gouverné est modifié.
Le contrôle Git reste conservé comme filet indépendant.
## Gate opérateur
Après application puis commit/push du history `FAIL` de `alpha.2`, appliquer ce delta et exécuter :
```bash
cat VERSION
test -f history/0.1.4/alpha.2.md
grep -A2 '^## Statut$' history/0.1.4/alpha.2.md | grep -Fx 'FAIL'
test -f deltas/0.1.4/alpha.2.fix.1.md
test ! -e history/0.1.4/alpha.2.fix.1.md
test -f scripts/audit_text_hygiene.py
test -f tests/test_text_hygiene.py
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_text_hygiene.py \
VERSION README.md RULES.md ROADMAP.md CHANGELOG.md \
docs deltas history prompts scripts tests templates .gitignore .settings
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
assert Path('VERSION').read_text(encoding='utf-8').strip() == '0.1.4-alpha.2.fix.1'
history = Path('history/0.1.4/alpha.2.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+FAIL', history)
study_path = Path('docs/studies/002-TAURI_SKELETON_DECISION.md')
study = study_path.read_bytes()
assert study.endswith(b'\n')
assert not study.endswith(b'\n\n')
assert study_path.read_text(encoding='utf-8').startswith(
'<!-- file: docs/studies/002-TAURI_SKELETON_DECISION.md -->\n'
'<!-- version: 3 -->'
)
workflow = Path('docs/rules/210-WORKFLOW.md').read_text(encoding='utf-8')
assert workflow.startswith(
'<!-- file: docs/rules/210-WORKFLOW.md -->\n'
'<!-- version: 8 -->'
)
for phrase in (
'## Hygiène mécanique des artefacts texte',
'exactement une seule newline finale',
'scripts/audit_text_hygiene.py',
'Un générateur MUST corriger un défaut mécanique détectable avant livraison',
):
assert phrase in workflow, phrase
matrix = Path('docs/validation/001-VALIDATION_MATRIX.md').read_text(encoding='utf-8')
assert matrix.startswith(
'<!-- file: docs/validation/001-VALIDATION_MATRIX.md -->\n'
'<!-- version: 15 -->'
)
assert '`PGR-TEXT-HYGIENE-001`' in matrix
assert 'exactement une seule newline finale' in matrix
assert Path('scripts/audit_text_hygiene.py').exists()
assert Path('tests/test_text_hygiene.py').exists()
for path, version in (
('docs/rules/710-TAURI.md', '7'),
('docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md', '2'),
('docs/000-README.md', '42'),
):
lines = Path(path).read_text(encoding='utf-8').splitlines()
assert lines[1] == f'<!-- version: {version} -->', (path, lines[1])
assert not Path('docs/skeletons/004-TAURI.md').exists()
assert not Path('history/0.1.4/alpha.2.fix.1.md').exists()
print(
'0.1.4 alpha.2.fix.1 hygiene audit: clean '
'(EOF corrected, reusable text hygiene audit active, Tauri decisions preserved)'
)
PY
git diff --check
git add -A
git diff --cached --check
git status --short
```
Le scope indexé attendu est :
```text
M VERSION
A deltas/0.1.4/alpha.2.fix.1.md
M docs/rules/210-WORKFLOW.md
M docs/studies/002-TAURI_SKELETON_DECISION.md
M docs/validation/001-VALIDATION_MATRIX.md
A scripts/audit_text_hygiene.py
A tests/test_text_hygiene.py
```
L'ordre d'affichage peut varier ; l'ensemble des chemins doit être identique.
## Transition
### PASS
Produire `history/0.1.4/alpha.2.fix.1.md`, commit/push sous l'identité `0.1.4-alpha.2.fix.1`, puis poursuivre avec `alpha.3` sur cette baseline propre. Les gates suivantes de `0.1.4` doivent sélectionner `PGR-TEXT-HYGIENE-001` pour les fichiers texte modifiés.
### FAIL
Enregistrer le résultat réel dans `history/0.1.4/alpha.2.fix.1.md` et poursuivre sous `alpha.2.fix.N`. Ne pas commencer `alpha.3` tant que l'hygiène texte et le scope du correctif ne sont pas `PASS`.

214
deltas/0.1.4/alpha.2.md Normal file
View File

@@ -0,0 +1,214 @@
<!-- file: deltas/0.1.4/alpha.2.md -->
<!-- version: 1 -->
# Delta 0.1.4-alpha.2 — réconciliation normative Tauri
## Objet
Réconcilier l'owner Tauri `710` et l'étude historique `002` à partir du cadrage `alpha.1` validé, sans matérialiser encore le skeleton `004-TAURI.md`.
La tranche sépare explicitement les responsabilités Tauri des choix Web déjà possédés par les owners `530/540/550/560`, précise la frontière commande / permission / capability et rend la politique de sélection des capability files visible comme décision de sécurité.
## Précondition
Le history `history/0.1.4/alpha.1.md` doit être présent avec statut `PASS` avant application de ce delta.
`alpha.1` a validé :
```text
48 / 48 tests PASS
Markdown headers: clean (266 file(s))
Markdown tables: clean (11 table(s), 266 file(s))
Markdown links: clean (343 local link(s), 266 file(s))
0.1.4 alpha.1 structural audit: clean (96 prior pairs, 7 current Tauri hosts classified, no premature skeleton/adoption)
```
## Réconciliation de `710-TAURI.md`
La révision interne passe de `6` à `7`.
La convention contrôlée est recentrée sur ce que Tauri possède réellement :
- host Cargo direct `lib + bin` recommandé pour une nouvelle baseline PGR contrôlée ;
- `src-tauri/` reste un layout Tauri supporté et n'est pas déclaré invalide ;
- `build.rs`, configuration Tauri, capabilities, assemblage Rust, hooks et packaging restent dans le scope Tauri ;
- la racine frontend est un point de composition, pas un choix possédé par `710` ;
- TypeScript, Vite, CSS/Sass, framework CSS et package manager restent possédés par leurs owners Web ;
- TS-RS devient un choix conditionnel de frontière typée plutôt qu'une obligation Tauri générale ;
- aucun template technique n'est créé.
La frontière de sécurité distingue désormais :
```text
commande enregistrée
permission ACL + scopes
capability assignant les permissions aux fenêtres/webviews
```
La tranche exige une décision explicite sur la sélection des capabilities. Elle enregistre le comportement Tauri 2 courant : si `app.security.capabilities` est absent ou vide, les capability files du répertoire `capabilities/` sont inclus par défaut ; une liste explicite permet de sélectionner ceux qui participent au build.
L'ajout d'un capability file sous auto-inclusion devient donc explicitement une modification de surface de sécurité. La revue doit également considérer le cumul des droits lorsqu'une fenêtre/webview appartient à plusieurs capabilities.
## Révision de l'étude `002`
La révision interne passe de `2` à `3`.
La décision `DEFER` de `0.0.5-alpha.9` reste conservée comme preuve historique mais n'est plus la décision active :
```text
motif Web historique LIFT
candidat organisationnel ADOPT FOR MATERIALIZATION
matérialisation pendant alpha.2 NO
matérialisation visée alpha.3
```
Le corpus courant reste `1` host Games `0.3.6` + `6` hosts KSP `0.3.19`. La future specification doit composer fondation + Rust/Cargo + Web applicable + Tauri + plateformes ciblées, sans recopier les owners.
## Mise à jour du plan et de l'index
`docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md` passe en révision `2` et enregistre :
- la gate `alpha.1 PASS` ;
- les décisions normatives préparées pour `alpha.2` ;
- l'autorisation conditionnelle de matérialiser `004-TAURI.md` en `alpha.3` ;
- le point transversal découvert lors de l'utilisation de PGR avec SaseDev Knowledge : sémantique `SHOULD`, autonomie post-adoption et future séparation PGR/Knowledge ;
- l'obligation de reprendre ce point lors de la revue d'horizon de fermeture avant de générer le prompt suivant.
`docs/000-README.md` passe en révision `42` pour refléter l'état réconcilié du profil et de l'étude.
`ROADMAP.md` et `CHANGELOG.md` restent inchangés. La trajectoire publiée `0.1.5` Games / `0.1.6` KSP / `0.1.7` audits Rust n'est pas réécrite avant la revue d'horizon prévue en fermeture de `0.1.4`.
## Frontières
Cette tranche MUST NOT :
- créer `docs/skeletons/004-TAURI.md` ;
- créer un template `tauri.conf.json`, `build.rs` ou capability générique ;
- créer un contrat `docs/validation/*TAURI*` séparé ;
- modifier `RULES.md` ou `230-ADOPTION.md` pour traiter dès maintenant le point transversal `SHOULD`/autonomie ;
- modifier `ROADMAP.md` ou `CHANGELOG.md` ;
- commencer l'adoption Games ou KSP.
## Gate opérateur
Après application du history `alpha.1`, commit/push de `alpha.1`, puis application du présent delta, exécuter depuis la racine du dépôt :
```bash
cat VERSION
test -f history/0.1.4/alpha.1.md
test -f deltas/0.1.4/alpha.2.md
test ! -e history/0.1.4/alpha.2.md
test ! -e docs/skeletons/004-TAURI.md
grep -A4 '^## Statut$' history/0.1.4/alpha.1.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
assert Path('VERSION').read_text(encoding='utf-8').strip() == '0.1.4-alpha.2'
history = Path('history/0.1.4/alpha.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS', history)
assert {p.name for p in Path('deltas/0.1.4').glob('*.md')} == {'alpha.1.md', 'alpha.2.md'}
assert {p.name for p in Path('history/0.1.4').glob('*.md')} == {'alpha.1.md'}
rule = Path('docs/rules/710-TAURI.md').read_text(encoding='utf-8')
assert rule.startswith('<!-- file: docs/rules/710-TAURI.md -->\n<!-- version: 7 -->')
for phrase in (
'## Commandes, permissions et capabilities',
'commande enregistrée → handler natif connu du système d\'invocation',
'app.security.capabilities',
'inclut par défaut les capability files du répertoire `capabilities/`',
'droits cumulés',
'Le choix ou le renforcement de TS-RS appartient au projet ou au futur skeleton Tauri',
'host SHOULD être une crate Cargo mixte directement lisible',
):
assert phrase in rule, phrase
for phrase in (
'TypeScript et Vite sont fortement recommandés',
'Bootstrap est la baseline de présentation privilégiée',
'MUST utiliser TS-RS',
):
assert phrase not in rule, phrase
study = Path('docs/studies/002-TAURI_SKELETON_DECISION.md').read_text(encoding='utf-8')
assert study.startswith('<!-- file: docs/studies/002-TAURI_SKELETON_DECISION.md -->\n<!-- version: 3 -->')
for phrase in (
'## Réexamen décisionnel `0.1.4-alpha.2`',
'DEFER historique pour absence d\'owners Web LIFT',
'candidat organisationnel ADOPT FOR MATERIALIZATION',
'matérialisation visée alpha.3',
'Le `DEFER` de `0.0.5-alpha.9` reste conservé comme décision historique',
):
assert phrase in study, phrase
plan = Path('docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
assert plan.startswith('<!-- file: docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md -->\n<!-- version: 2 -->')
for phrase in (
'## Gate `alpha.1` acquise',
'## Réconciliation normative préparée en `alpha.2`',
'## Point transversal découvert pendant la gate `alpha.1`',
'forte recommandation non obligatoire',
'sans rechercher automatiquement une version PGR plus récente',
'howtos, recettes et snippets pratiques vivent dans Knowledge',
'revue d\'horizon',
):
assert phrase in plan, phrase
index = Path('docs/000-README.md').read_text(encoding='utf-8')
assert index.startswith('<!-- file: docs/000-README.md -->\n<!-- version: 42 -->')
assert 'owner Tauri 2 réconcilié en `alpha.2`' in index
assert 'candidat organisationnel retenu pour matérialisation contrôlée en `alpha.3`' in index
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
for phrase in (
'`( ) 0.1.4`',
'`( ) 0.1.5` — adoption réelle de PGR par `sasedev-games`',
'`( ) 0.1.6` — adoption réelle de PGR par `khadhroony-solana-project`',
'`( ) 0.1.7` — audits Python read-only',
):
assert phrase in roadmap, phrase
assert '0.1.8' not in roadmap
assert not Path('docs/skeletons/004-TAURI.md').exists()
assert not Path('history/0.1.4/alpha.2.md').exists()
print(
'0.1.4 alpha.2 Tauri normative audit: clean '
'(ACL boundaries explicit, Web ownership separated, historical DEFER lifted, skeleton still deferred to alpha.3)'
)
PY
git diff --check
git add VERSION \
deltas/0.1.4/alpha.2.md \
docs/000-README.md \
docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md \
docs/rules/710-TAURI.md \
docs/studies/002-TAURI_SKELETON_DECISION.md
git diff --cached --check
git status --short
```
Le scope attendu du delta `alpha.2` est :
```text
M VERSION
A deltas/0.1.4/alpha.2.md
M docs/000-README.md
M docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
M docs/rules/710-TAURI.md
M docs/studies/002-TAURI_SKELETON_DECISION.md
```

202
deltas/0.1.4/alpha.3.md Normal file
View File

@@ -0,0 +1,202 @@
<!-- file: deltas/0.1.4/alpha.3.md -->
<!-- version: 1 -->
# Delta 0.1.4-alpha.3 — skeleton Tauri contrôlé
## Précondition
`0.1.4-alpha.2.fix.1` doit être committée avec son history `PASS` avant application de ce delta.
Version après application :
```text
0.1.4-alpha.3
```
## Objet
Matérialiser le skeleton Tauri 2 autorisé par les gates précédentes, sans créer de template technique universel ni absorber les owners Rust/Web/plateforme.
La tranche corrige également le contrat de packaging des archives delta/history après l'observation opérateur d'un répertoire englobant `pgr/` dans deux ZIP remis : les entrées doivent désormais être directement relatives à la racine du dépôt.
## Scope
ADD :
```text
deltas/0.1.4/alpha.3.md
docs/skeletons/004-TAURI.md
```
REPLACE :
```text
VERSION
docs/000-README.md
docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
docs/rules/210-WORKFLOW.md
docs/skeletons/000-README.md
```
Aucun template Tauri, contrat de validation Tauri séparé, changement de roadmap ou adoption Games/KSP n'appartient à cette tranche.
## Skeleton `004-TAURI`
La nouvelle specification :
- compose `001-PROJECT_GOVERNANCE_FOUNDATION`, `002-RUST_CARGO_WORKSPACE`, `003-WEB_FRONTEND` et `710-TAURI` ;
- conserve `src-tauri/` comme layout valide pour un projet existant tout en recommandant une crate Cargo directement lisible pour une nouvelle baseline contrôlée ;
- rend obligatoires les décisions de version, frontend, package manager, hooks, `devUrl`, `frontendDist`, capabilities, permissions, plugins, fenêtres, bundles et plateformes ;
- distingue recommandations de baseline et options locales ;
- garde WASM séparé par défaut ;
- définit un ordre d'initialisation ;
- définit une gate initiale séparant preuves Rust, frontend, intégration Tauri, packaging et plateforme ;
- conclut qu'aucun template Tauri technique supplémentaire n'est actuellement justifié.
## Packaging delta/history
`docs/rules/210-WORKFLOW.md` passe en révision `9` et rend explicite que :
```text
archive.delta/history.zip
├── VERSION # si présent dans le delta
├── docs/...
├── deltas/...
└── history/...
```
est valide, tandis que :
```text
archive.zip
└── pgr/
├── docs/...
└── history/...
```
est invalide pour le handoff canonique `unzip -o <archive> -d .`.
Le générateur doit vérifier la liste des entrées du ZIP avant remise.
## Gate opérateur
Après commit/push du history `PASS` de `alpha.2.fix.1`, appliquer ce delta puis exécuter :
```bash
cat VERSION
test -f history/0.1.4/alpha.2.fix.1.md
grep -A2 '^## Statut$' history/0.1.4/alpha.2.fix.1.md | grep -Fx 'PASS'
test -f deltas/0.1.4/alpha.3.md
test -f docs/skeletons/004-TAURI.md
test ! -e history/0.1.4/alpha.3.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_text_hygiene.py \
VERSION README.md RULES.md ROADMAP.md CHANGELOG.md \
docs deltas history prompts scripts tests templates .gitignore .settings
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
assert Path('VERSION').read_text(encoding='utf-8').strip() == '0.1.4-alpha.3'
history = Path('history/0.1.4/alpha.2.fix.1.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS', history)
skeleton = Path('docs/skeletons/004-TAURI.md').read_text(encoding='utf-8')
assert skeleton.startswith(
'<!-- file: docs/skeletons/004-TAURI.md -->\n'
'<!-- version: 1 -->'
)
for phrase in (
'## Décisions obligatoires avant matérialisation',
'## Baseline organisationnelle recommandée',
'## Capabilities, permissions et commandes',
'## Ordre d\'initialisation',
'## Validation initiale',
'## Templates techniques',
'Aucun template Tauri technique supplémentaire n\'est requis',
'ADOPT / KEEP-LOCAL / OVERRIDE / DEFER',
):
assert phrase in skeleton, phrase
for path, version in (
('docs/rules/210-WORKFLOW.md', '9'),
('docs/skeletons/000-README.md', '7'),
('docs/000-README.md', '43'),
('docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md', '3'),
('docs/rules/710-TAURI.md', '7'),
('docs/studies/002-TAURI_SKELETON_DECISION.md', '3'),
):
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')
for phrase in (
'Les entrées des archives delta/history MUST utiliser directement les chemins relatifs à la racine du dépôt',
'MUST NOT ajouter un répertoire englobant portant le nom du projet',
'vérifier la liste des entrées du ZIP avant remise',
):
assert phrase in workflow, phrase
index = Path('docs/skeletons/000-README.md').read_text(encoding='utf-8')
assert '[`004-TAURI.md`](004-TAURI.md)' in index
doc_index = Path('docs/000-README.md').read_text(encoding='utf-8')
assert '[`skeletons/004-TAURI.md`](skeletons/004-TAURI.md)' in doc_index
assert not Path('history/0.1.4/alpha.3.md').exists()
assert not Path('docs/templates/011-TAURI.md').exists()
assert not Path('docs/validation/006-TAURI_VALIDATION.md').exists()
print(
'0.1.4 alpha.3 skeleton audit: clean '
'(004 materialized, owners composed, no premature template/validation artifact, ZIP root contract explicit)'
)
PY
git diff --check
git add VERSION \
deltas/0.1.4/alpha.3.md \
docs/000-README.md \
docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md \
docs/rules/210-WORKFLOW.md \
docs/skeletons/000-README.md \
docs/skeletons/004-TAURI.md
git diff --cached --check
git status --short
```
Le scope attendu est :
```text
M VERSION
A deltas/0.1.4/alpha.3.md
M docs/000-README.md
M docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
M docs/rules/210-WORKFLOW.md
M docs/skeletons/000-README.md
A docs/skeletons/004-TAURI.md
```
## Transition
### PASS
Produire `history/0.1.4/alpha.3.md`, commit/push sous l'identité `0.1.4-alpha.3`, puis ouvrir `beta.1` pour la réconciliation globale et la décision explicite sur les artefacts Tauri supplémentaires.
### FAIL
Enregistrer le résultat réel dans `history/0.1.4/alpha.3.md` et poursuivre sous `alpha.3.fix.N`. Ne pas ouvrir `beta.1` tant que la composition du skeleton et le scope ne sont pas propres.

189
deltas/0.1.4/beta.1.md Normal file
View File

@@ -0,0 +1,189 @@
<!-- file: deltas/0.1.4/beta.1.md -->
<!-- version: 1 -->
# Delta 0.1.4-beta.1 — réconciliation des artefacts Tauri
## Objet
Fermer la phase de conception Tauri de `0.1.4` en réconciliant les artefacts matérialisés, en vérifiant leurs owners et en décidant explicitement de ne pas créer de template technique Tauri, de contrat de validation Tauri séparé ou de dry-run factice en l'absence de lacune démontrée.
## Préconditions
- `0.1.4-alpha.3` est validée `PASS` et son history est présent ;
- `docs/skeletons/004-TAURI.md` est matérialisé ;
- `docs/rules/710-TAURI.md` reste l'owner Tauri en révision interne `7` ;
- aucun `docs/templates/011-TAURI.md` ni `docs/validation/006-TAURI_VALIDATION.md` n'existe ;
- les archives delta/history restent relatives directement à la racine du dépôt.
## Modifications
- `VERSION` passe à `0.1.4-beta.1` ;
- `docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md` passe en révision `4` et enregistre la gate `alpha.3` ainsi que les décisions d'artefacts de `beta.1` ;
- `docs/studies/002-TAURI_SKELETON_DECISION.md` passe en révision `4` et ferme explicitement la décision sur template, validation séparée et dry-run ;
- `docs/000-README.md` passe en révision `44` et indexe l'état `beta.1` ;
- aucun nouvel owner, template ou contrat de validation Tauri n'est créé.
## Décision attendue
```text
004-TAURI.md KEEP
template technique Tauri générique DO NOT CREATE
006-TAURI_VALIDATION.md DO NOT CREATE
dry-run exécutable d'un faux projet NOT REQUIRED
audit statique de composition REQUIRED
```
L'absence d'artefact supplémentaire est une décision positive : un fichier nouveau n'est justifié que s'il possède une responsabilité réutilisable non déjà couverte.
## Gate opérateur
```bash
cat VERSION
test -f history/0.1.4/alpha.3.md
grep -A2 '^## Statut$' history/0.1.4/alpha.3.md | grep -Fx 'PASS'
test -f docs/skeletons/004-TAURI.md
test ! -e docs/templates/011-TAURI.md
test ! -e docs/validation/006-TAURI_VALIDATION.md
test ! -e history/0.1.4/beta.1.md
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_text_hygiene.py \
VERSION README.md RULES.md ROADMAP.md CHANGELOG.md \
docs deltas history prompts scripts tests templates .gitignore .settings
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
assert Path('VERSION').read_text(encoding='utf-8').strip() == '0.1.4-beta.1'
history = Path('history/0.1.4/alpha.3.md').read_text(encoding='utf-8')
assert re.search(r'## Statut\s+PASS', history)
expected_deltas = {
'alpha.1.md',
'alpha.2.md',
'alpha.2.fix.1.md',
'alpha.3.md',
'beta.1.md',
}
expected_histories = {
'alpha.1.md',
'alpha.2.md',
'alpha.2.fix.1.md',
'alpha.3.md',
}
assert {p.name for p in Path('deltas/0.1.4').glob('*.md')} == expected_deltas
assert {p.name for p in Path('history/0.1.4').glob('*.md')} == expected_histories
plan = Path('docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
assert plan.startswith(
'<!-- file: docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md -->\n'
'<!-- version: 4 -->'
)
for phrase in (
'## Gate `alpha.3` acquise',
"## Réconciliation d'artefacts préparée en `beta.1`",
'template technique Tauri générique DO NOT CREATE',
'006-TAURI_VALIDATION.md DO NOT CREATE',
"dry-run exécutable d'un faux projet NOT REQUIRED",
'audit statique de composition REQUIRED',
):
assert phrase in plan, phrase
study = Path('docs/studies/002-TAURI_SKELETON_DECISION.md').read_text(encoding='utf-8')
assert study.startswith(
'<!-- file: docs/studies/002-TAURI_SKELETON_DECISION.md -->\n'
'<!-- version: 4 -->'
)
for phrase in (
'## Réconciliation finale des artefacts `0.1.4-beta.1`',
'Décision : **DO NOT CREATE**.',
'Décision : **NOT REQUIRED** pour `0.1.4-beta.1`.',
'004-TAURI.md KEEP',
'template Tauri générique DO NOT CREATE',
'validation Tauri séparée DO NOT CREATE',
'artefact supplémentaire sans lacune réelle FORBIDDEN BY DEFAULT',
):
assert phrase in study, phrase
skeleton = Path('docs/skeletons/004-TAURI.md').read_text(encoding='utf-8')
for ref in (
'001-PROJECT_GOVERNANCE_FOUNDATION',
'002-RUST_CARGO_WORKSPACE',
'003-WEB_FRONTEND',
'710 TAURI',
):
assert ref in skeleton, ref
for path in (
'docs/skeletons/001-PROJECT_GOVERNANCE_FOUNDATION.md',
'docs/skeletons/002-RUST_CARGO_WORKSPACE.md',
'docs/skeletons/003-WEB_FRONTEND.md',
'docs/rules/710-TAURI.md',
'docs/validation/005-WEB_FRONTEND_VALIDATION.md',
):
assert Path(path).is_file(), path
assert not Path('docs/templates/011-TAURI.md').exists()
assert not Path('docs/validation/006-TAURI_VALIDATION.md').exists()
assert not Path('history/0.1.4/beta.1.md').exists()
index = Path('docs/000-README.md').read_text(encoding='utf-8')
assert index.startswith(
'<!-- file: docs/000-README.md -->\n'
'<!-- version: 44 -->'
)
assert '`004-TAURI.md` suffit' in index
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
for phrase in (
'`( ) 0.1.4`',
'`( ) 0.1.5` — adoption réelle de PGR par `sasedev-games`',
'`( ) 0.1.6` — adoption réelle de PGR par `khadhroony-solana-project`',
'`( ) 0.1.7` — audits Python read-only',
):
assert phrase in roadmap, phrase
assert '0.1.8' not in roadmap
print(
'0.1.4 beta.1 artifact audit: clean '
'(004 sufficient, ownership composed, no redundant template/validation contract, no fake dry-run)'
)
PY
git diff --check
git add VERSION \
deltas/0.1.4/beta.1.md \
docs/000-README.md \
docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md \
docs/studies/002-TAURI_SKELETON_DECISION.md
git diff --cached --check
git status --short
```
## Scope Git attendu
```text
M VERSION
A deltas/0.1.4/beta.1.md
M docs/000-README.md
M docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
M docs/studies/002-TAURI_SKELETON_DECISION.md
```
## Suite
Si la gate est `PASS`, produire `history/0.1.4/beta.1.md`, committer/pousser la tranche puis préparer `rc.1` avec freeze Tauri, changelog candidate et revue d'horizon transversale avant génération du prochain start prompt.

203
deltas/0.1.4/rc.1.md Normal file
View File

@@ -0,0 +1,203 @@
<!-- file: deltas/0.1.4/rc.1.md -->
<!-- version: 1 -->
# Delta 0.1.4-rc.1 — freeze Tauri et revue d’horizon
## Objet
Geler le scope Tauri validé par `beta.1`, préparer le changelog candidat et exécuter la revue d’horizon transversale exigée par le plan avant de générer le prochain start prompt.
La RC ne corrige pas encore la sémantique `SHOULD`, le contrat d’autonomie ou la frontière PGR / Knowledge : elle décide explicitement qu’ils forment la prochaine release `0.1.5` et décale les adoptions Games/KSP afin qu’elles utilisent ensuite ce contrat stabilisé.
## Préconditions
- `0.1.4-beta.1` est validée `PASS` et son history est présent ;
- `710-TAURI.md` reste en révision `7` et `004-TAURI.md` en révision `1` ;
- aucun template technique Tauri ni `006-TAURI_VALIDATION.md` n’est requis ;
- les trois questions transversales enregistrées dans le plan doivent être décidées avant création du prompt suivant ;
- les archives delta/history restent relatives directement à la racine du dépôt.
## Modifications
- `VERSION` passe à `0.1.4-rc.1` ;
- `CHANGELOG.md` reçoit l’entrée `0.1.4 (candidate)` sans chronologie de tranches ;
- `ROADMAP.md` enregistre la revue d’horizon : `0.1.5` gouvernance/autonomie, `0.1.6` Games, `0.1.7` KSP, `0.1.8` audits Rust ;
- `docs/studies/004-V0_1_4_HORIZON_REVIEW.md` matérialise la décision et ses limites ;
- `prompts/011-V0_1_5_START_PROMPT.md` prépare la prochaine release à partir d’une future stable `v0.1.4` réellement publiée ;
- le plan et les index sont mis à jour pour refléter le freeze et le handoff ;
- aucun owner normatif transversal n’est encore modifié en RC.
## Gate opérateur
```bash
cat VERSION
test -f history/0.1.4/beta.1.md
grep -A2 '^## Statut$' history/0.1.4/beta.1.md | grep -Fx 'PASS'
test -f docs/studies/004-V0_1_4_HORIZON_REVIEW.md
test -f prompts/011-V0_1_5_START_PROMPT.md
test ! -e history/0.1.4/rc.1.md
grep -Fx '<!-- version: 18 -->' CHANGELOG.md
grep -Fx '<!-- version: 16 -->' ROADMAP.md
grep -Fx '<!-- version: 45 -->' docs/000-README.md
grep -Fx '<!-- version: 5 -->' docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
grep -Fx '<!-- version: 5 -->' docs/studies/000-README.md
grep -Fx '<!-- version: 1 -->' docs/studies/004-V0_1_4_HORIZON_REVIEW.md
grep -Fx '<!-- version: 1 -->' prompts/011-V0_1_5_START_PROMPT.md
python3 -B - <<'PYGATE'
from pathlib import Path
import re
assert Path('VERSION').read_text(encoding='utf-8').strip() == '0.1.4-rc.1'
expected_statuses = {
'alpha.1.md': 'PASS',
'alpha.2.md': 'FAIL',
'alpha.2.fix.1.md': 'PASS',
'alpha.3.md': 'PASS',
'beta.1.md': 'PASS',
}
for name, status in expected_statuses.items():
delta = Path('deltas/0.1.4', name)
history = Path('history/0.1.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.1.4').glob('*.md')} - {
p.name for p in Path('history/0.1.4').glob('*.md')
}
assert pending == {'rc.1.md'}, pending
for path, version in (
('docs/rules/710-TAURI.md', 7),
('docs/skeletons/004-TAURI.md', 1),
('docs/studies/002-TAURI_SKELETON_DECISION.md', 4),
('RULES.md', 14),
('docs/rules/230-ADOPTION.md', 1),
('docs/rules/400-VALIDATION.md', 1),
):
lines = Path(path).read_text(encoding='utf-8').splitlines()
assert lines[1] == f'<!-- version: {version} -->', (path, lines[1])
changelog = Path('CHANGELOG.md').read_text(encoding='utf-8')
assert '## 0.1.4 (candidate)' in changelog
section = changelog.split('## 0.1.4 (candidate)', 1)[1].split('## 0.1.3', 1)[0]
for phrase in (
'skeleton Tauri',
'commandes, permissions et capabilities',
'004-TAURI.md',
'audit réutilisable d’hygiène texte',
'0.1.5',
'0.1.8',
):
assert phrase in section, phrase
for forbidden in ('alpha.1', 'alpha.2', 'alpha.3', 'beta.1', 'rc.1', 'rel.1'):
assert forbidden not in section, forbidden
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
for phrase in (
'`( ) 0.1.4` — domaine Tauri',
'`( ) 0.1.5` — sémantique normative et autonomie',
'`( ) 0.1.6` — adoption réelle de PGR par `sasedev-games`',
'`( ) 0.1.7` — adoption réelle de PGR par `khadhroony-solana-project`',
'`( ) 0.1.8` — audits Python read-only',
):
assert phrase in roadmap, phrase
assert '`( ) 0.1.9`' not in roadmap
assert "skeleton Tauri jusqu'au réexamen 0.1.4" not in roadmap
study = Path('docs/studies/004-V0_1_4_HORIZON_REVIEW.md').read_text(encoding='utf-8')
for phrase in (
'forte recommandation',
'MUST NOT faire échouer à lui seul une gate',
'baseline locale du projet',
'règles locales = autorité des sessions/releases suivantes',
'PGR MUST rester auto-suffisant',
'une release de gouvernance/autonomie doit précéder les adoptions Games/KSP',
'0.1.8 audits Rust/Clippy read-only',
):
assert phrase in study, phrase
prompt = Path('prompts/011-V0_1_5_START_PROMPT.md').read_text(encoding='utf-8')
for phrase in (
'tag Gitea `v0.1.4`',
'pgr-0.1.4-publish.001-report.md',
'0.1.5-alpha.1',
'004-V0_1_4_HORIZON_REVIEW.md',
'forte recommandation non obligatoire',
'ne doivent ni rechercher automatiquement « la dernière version de PGR »',
'SaseDev Knowledge',
'réservée à `0.1.6`',
'réservée à `0.1.7`',
'réservés à `0.1.8`',
):
assert phrase in prompt, phrase
plan = Path('docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'## Gate `beta.1` acquise',
'## Revue d’horizon préparée en `rc.1`',
'0.1.5 sémantique normative + autonomie + frontière PGR/Knowledge',
'Le prompt `011` transmet explicitement leur réexamen à `0.1.5-alpha.1`.',
):
assert phrase in plan, phrase
assert not Path('docs/templates/011-TAURI.md').exists()
assert not Path('docs/validation/006-TAURI_VALIDATION.md').exists()
assert not Path('history/0.1.4/rc.1.md').exists()
print(
'0.1.4 rc.1 integration audit: clean '
'(beta PASS, Tauri frozen, horizon reordered to governance 0.1.5 before Games/KSP, prompt 011 verified)'
)
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_text_hygiene.py \
VERSION README.md RULES.md ROADMAP.md CHANGELOG.md \
docs deltas history prompts scripts tests templates .gitignore .settings
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 ROADMAP.md \
deltas/0.1.4/rc.1.md \
docs/000-README.md \
docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md \
docs/studies/000-README.md \
docs/studies/004-V0_1_4_HORIZON_REVIEW.md \
prompts/011-V0_1_5_START_PROMPT.md
git diff --cached --check
git status --short
```
## Scope Git attendu
```text
M CHANGELOG.md
M ROADMAP.md
M VERSION
A deltas/0.1.4/rc.1.md
M docs/000-README.md
M docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
M docs/studies/000-README.md
A docs/studies/004-V0_1_4_HORIZON_REVIEW.md
A prompts/011-V0_1_5_START_PROMPT.md
```
## Transition
Si la gate est `PASS`, produire `history/0.1.4/rc.1.md`, committer/pousser `0.1.4-rc.1`, puis préparer la promotion mécanique `rel.1` sans rouvrir le scope Tauri ni commencer `0.1.5`.

233
deltas/0.1.4/rel.1.md Normal file
View File

@@ -0,0 +1,233 @@
<!-- file: deltas/0.1.4/rel.1.md -->
<!-- version: 1 -->
# Delta 0.1.4 rel.1 — promotion stable pré-tag
## Baseline et version
Baseline : `0.1.4-rc.1`, avec `history/0.1.4/rc.1.md` appliqué et committé. Ce delta MUST NOT être appliqué avant ce commit.
Version avant application :
```text
0.1.4-rc.1
```
Version après application :
```text
0.1.4
```
`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.4` sans rouvrir le scope Tauri et sans commencer `0.1.5`.
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 `010` historique. Aucun owner Tauri, skeleton, étude technique, audit Python ou règle normative réservée à `0.1.5` n'est modifié.
La validation de cette tranche est **pré-tag**. Le tag `v0.1.4`, son archive source Gitea et le rapport `pgr-0.1.4-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.4` et la publication réelle du tag.
## Scope
REPLACE :
```text
VERSION
README.md
ROADMAP.md
CHANGELOG.md
docs/000-README.md
docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
```
ADD :
```text
deltas/0.1.4/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.4/rc.1.md` :
```bash
test "$(cat VERSION)" = '0.1.4'
git cat-file -e HEAD:history/0.1.4/rc.1.md
test -f history/0.1.4/rc.1.md
test -f deltas/0.1.4/rel.1.md
test -f prompts/011-V0_1_5_START_PROMPT.md
test ! -e history/0.1.4/rel.1.md
grep -A2 '^## Statut$' history/0.1.4/rc.1.md | grep -Fx 'PASS'
grep -Fx '<!-- version: 27 -->' README.md
grep -Fx '<!-- version: 17 -->' ROADMAP.md
grep -Fx '<!-- version: 19 -->' CHANGELOG.md
grep -Fx '<!-- version: 46 -->' docs/000-README.md
grep -Fx '<!-- version: 6 -->' docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
grep -F -- '- `(x) 0.1.4`' ROADMAP.md
grep -Fx '## 0.1.4' CHANGELOG.md
grep -F 'La stable `0.1.4` réexamine le domaine Tauri' README.md
grep -F 'plan historique de la stable `0.1.4`' 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',
'beta.1.md': 'PASS',
'rc.1.md': 'PASS',
}
for name, status in expected.items():
delta = Path('deltas/0.1.4', name)
history = Path('history/0.1.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 = {path.name for path in Path('deltas/0.1.4').glob('*.md')} - {
path.name for path in Path('history/0.1.4').glob('*.md')
}
assert pending == {'rel.1.md'}, pending
roadmap = Path('ROADMAP.md').read_text(encoding='utf-8')
assert '- `(x) 0.1.4`' in roadmap
for version in ('0.1.5', '0.1.6', '0.1.7', '0.1.8'):
assert f'- `( ) {version}`' in roadmap, version
assert '- `( ) 0.1.9`' not in roadmap
changelog = Path('CHANGELOG.md').read_text(encoding='utf-8')
assert '## 0.1.4' in changelog.splitlines()
assert '## 0.1.4 (candidate)' not in changelog
section = changelog.split('## 0.1.4', 1)[1].split('## 0.1.3', 1)[0]
for phrase in (
'skeleton Tauri',
'commandes, permissions et capabilities',
'004-TAURI.md',
'audit réutilisable d’hygiène texte',
'0.1.5',
'0.1.8',
):
assert phrase in section, phrase
for forbidden in ('alpha.1', 'alpha.2', 'alpha.3', 'beta.1', 'rc.1', 'rel.1'):
assert forbidden not in section, forbidden
readme = Path('README.md').read_text(encoding='utf-8')
for phrase in (
'La stable `0.1.4` réexamine le domaine Tauri',
'skeleton organisationnel `004-TAURI.md`',
'audit réutilisable d’hygiène texte',
'0.1.5',
'0.1.6',
'0.1.7',
):
assert phrase in readme, phrase
index = Path('docs/000-README.md').read_text(encoding='utf-8')
assert 'plan historique de la stable `0.1.4`' in index
assert 'handoff de la stable `0.1.4` vers `0.1.5-alpha.1`' in index
plan = Path('docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md').read_text(encoding='utf-8')
for phrase in (
'Plan historique de la stable `0.1.4`',
'## Gate `rc.1` acquise et promotion stable',
'history/0.1.4/rel.1.md',
'pgr-0.1.4-publish.001-report.md',
'commit stable `0.1.4`',
):
assert phrase in plan, phrase
prompt = Path('prompts/011-V0_1_5_START_PROMPT.md').read_text(encoding='utf-8')
for phrase in (
'tag Gitea `v0.1.4`',
'pgr-0.1.4-publish.001-report.md',
'0.1.5-alpha.1',
'004-V0_1_4_HORIZON_REVIEW.md',
'forte recommandation non obligatoire',
'SaseDev Knowledge',
'réservée à `0.1.6`',
'réservée à `0.1.7`',
'réservés à `0.1.8`',
):
assert phrase in prompt, phrase
for path, version in (
('docs/rules/710-TAURI.md', 7),
('docs/skeletons/004-TAURI.md', 1),
('docs/studies/002-TAURI_SKELETON_DECISION.md', 4),
('docs/studies/004-V0_1_4_HORIZON_REVIEW.md', 1),
('RULES.md', 14),
('docs/rules/230-ADOPTION.md', 1),
('docs/rules/400-VALIDATION.md', 1),
):
lines = Path(path).read_text(encoding='utf-8').splitlines()
assert lines[1] == f'<!-- version: {version} -->', (path, lines[1])
assert not Path('docs/templates/011-TAURI.md').exists()
assert not Path('docs/validation/006-TAURI_VALIDATION.md').exists()
print(
'0.1.4 rel.1 stable gate audit: clean '
'(6 prior histories including expected alpha.2 FAIL/fix PASS, rel.1 pending, stable Tauri presentation and 0.1.5 handoff coherent)'
)
PYGATE
python3 -B -m unittest discover -s tests -v
python3 -B scripts/audit_text_hygiene.py \
VERSION README.md RULES.md ROADMAP.md CHANGELOG.md \
docs deltas history prompts scripts tests templates .gitignore .settings
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 \
deltas/0.1.4/rel.1.md \
docs/000-README.md \
docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
git diff --cached --check
git status --short
```
## Scope Git attendu
```text
M CHANGELOG.md
M README.md
M ROADMAP.md
M VERSION
A deltas/0.1.4/rel.1.md
M docs/000-README.md
M docs/plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md
```
## Transition après PASS
Si cette gate pré-tag est `PASS` :
1. produire `history/0.1.4/rel.1.md` avec les preuves opérateur réelles ;
2. appliquer ce history ;
3. `git add -A`, `git diff --cached --check`, puis committer **`0.1.4`** sans suffixe `rel.1` ;
4. pousser `master` ;
5. vérifier un workspace propre ;
6. créer et pousser le tag annoté `v0.1.4` ;
7. télécharger l'archive Gitea du tag et produire `pgr-0.1.4-publish.001-report.md` après vérification indépendante ;
8. seulement après `publish.001 PASS`, ouvrir la session `0.1.5` avec `prompts/011-V0_1_5_START_PROMPT.md`.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/000-README.md -->
<!-- version: 1 -->
<!-- version: 46 -->
# Documentation PGR
@@ -10,9 +10,90 @@ 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.
D'autres collections telles que `ideas/`, `studies/`, `reference/`, `formats/` ou `templates/` ne sont créées que lorsqu'un premier artefact réel les justifie.
D'autres collections telles que `ideas/`, `studies/`, `reference/` ou `formats/` ne sont créées que lorsqu'un premier artefact réel les justifie.
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.
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.1.4
- [`plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md`](plans/010-V0_1_4_TAURI_REEVALUATION_PLAN.md) — plan historique de la stable `0.1.4` : réexamen Tauri, skeleton `004`, décision d’artefacts, freeze RC et revue d’horizon.
- [`rules/710-TAURI.md`](rules/710-TAURI.md) — owner Tauri 2 réconcilié en `alpha.2` : host/orchestration, frontière commandes-permissions-capabilities, sélection des capabilities, plugins, version produit et validation proportionnée, sans absorber les choix Web.
- [`skeletons/003-WEB_FRONTEND.md`](skeletons/003-WEB_FRONTEND.md) — specialization Web composable dont l'existence satisfait les prérequis historiques sans rendre Vite, TypeScript, Sass, Bootstrap ou `frontend/` universels à Tauri.
- [`skeletons/004-TAURI.md`](skeletons/004-TAURI.md) — skeleton Tauri 2 matérialisé en `alpha.3`, composant fondation, Rust/Cargo, Web et owner `710` sans template technique universel ni copie des choix Games/KSP.
- [`studies/002-TAURI_SKELETON_DECISION.md`](studies/002-TAURI_SKELETON_DECISION.md) — décision historique `DEFER`, levée du motif Web puis décision `beta.1` : `004-TAURI.md` suffit ; aucun template technique ni contrat de validation Tauri séparé n'est justifié.
- [`studies/004-V0_1_4_HORIZON_REVIEW.md`](studies/004-V0_1_4_HORIZON_REVIEW.md) — revue de fermeture `rc.1` décidant de stabiliser en `0.1.5` la sémantique `SHOULD`, l’autonomie après adoption et la frontière PGR / SaseDev Knowledge avant Games/KSP.
- [`../prompts/011-V0_1_5_START_PROMPT.md`](../prompts/011-V0_1_5_START_PROMPT.md) — handoff de la stable `0.1.4` vers `0.1.5-alpha.1`, à exécuter uniquement après publication et vérification post-tag de `v0.1.4`.
- [`../prompts/010-V0_1_4_START_PROMPT.md`](../prompts/010-V0_1_4_START_PROMPT.md) — contrat de reprise exécuté pour ouvrir `0.1.4-alpha.1` après publication vérifiée de `v0.1.3`.
## Points d'entrée de 0.1.3
- [`plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md`](plans/009-V0_1_3_ANDROID_REEVALUATION_PLAN.md) — plan historique de la stable `0.1.3`, de l'audit Games à la stabilisation du profil Android générique et au handoff Tauri `0.1.4`.
- [`rules/610-ANDROID.md`](rules/610-ANDROID.md) — owner Android révisé : contrats SDK/identité/signing, natif/ABI, Lint, niveaux de tests, packaging/distribution et 16 KB conditionnel, sans absorber les choix propres à Games.
- [`rules/520-JAVA.md`](rules/520-JAVA.md) et [`rules/522-GRADLE.md`](rules/522-GRADLE.md) — owners composés uniquement lorsqu'un projet Android contient réellement du Java ou utilise Gradle.
- [`rules/600-PLATFORMS.md`](rules/600-PLATFORMS.md) et [`rules/400-VALIDATION.md`](rules/400-VALIDATION.md) — contrats généraux de plateforme et de preuve auxquels la spécialisation Android doit rester conforme.
- [`studies/003-V0_1_0_HORIZON_REVIEW.md`](studies/003-V0_1_0_HORIZON_REVIEW.md) — revue ayant engagé Android `0.1.3`, Tauri `0.1.4` puis l'adoption Games `0.1.5` comme scopes distincts.
- [`../prompts/009-V0_1_3_START_PROMPT.md`](../prompts/009-V0_1_3_START_PROMPT.md) — contrat de reprise exécuté pour ouvrir `0.1.3-alpha.1` après publication vérifiée de `v0.1.2`.
- [`../prompts/010-V0_1_4_START_PROMPT.md`](../prompts/010-V0_1_4_START_PROMPT.md) — prompt préparé par la RC pour le réexamen Tauri `0.1.4`, à exécuter uniquement après publication et vérification post-tag de `v0.1.3`.
## Points d'entrée de 0.1.2
- [`plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md`](plans/008-V0_1_2_JAVA_GRADLE_REEVALUATION_PLAN.md) — plan historique de la stable `0.1.2`, de la réévaluation Games à la scission `520/521/522`, avec frontière Android explicite.
- [`rules/520-JAVA.md`](rules/520-JAVA.md) — owner Java issu de la réévaluation du profil historique combiné ; il possède JDK, compatibilité source/bytecode, structure, API et tests Java.
- [`rules/521-MAVEN.md`](rules/521-MAVEN.md) — spécialisation Maven séparée afin que Maven ne devienne pas implicitement applicable à tout projet Java.
- [`rules/522-GRADLE.md`](rules/522-GRADLE.md) — spécialisation Gradle éprouvée contre Games, avec ownership du build, politique Wrapper/système et propriétés partagées/locales.
- [`rules/610-ANDROID.md`](rules/610-ANDROID.md) — owner de contrôle de frontière ; AGP, SDK/NDK, ABI/JNI, manifests, packaging/signing et smokes Android restent hors du scope `0.1.2`.
- [`studies/003-V0_1_0_HORIZON_REVIEW.md`](studies/003-V0_1_0_HORIZON_REVIEW.md) — revue ayant engagé `0.1.2` puis la réévaluation Android `0.1.3` comme releases distinctes.
- [`../prompts/008-V0_1_2_START_PROMPT.md`](../prompts/008-V0_1_2_START_PROMPT.md) — contrat de reprise autoritaire exécuté pour ouvrir `0.1.2-alpha.1` après publication vérifiée de `v0.1.1`.
- [`../prompts/009-V0_1_3_START_PROMPT.md`](../prompts/009-V0_1_3_START_PROMPT.md) — prompt préparé par la RC pour la réévaluation Android `0.1.3`, à exécuter uniquement après publication et vérification post-tag de `v0.1.2`.
## 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), [`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

@@ -0,0 +1,300 @@
<!-- file: docs/architecture/003-RULE_PROFILE_MODEL.md -->
<!-- version: 8 -->
# Modèle de profils de règles PGR
## Rôle
Un profil PGR est un ensemble cohérent de règles réutilisables dont le scope est plus spécifique que les règles générales.
Un profil ne constitue ni un catalogue de dépendances, ni un template technique, ni un skeleton de projet. Il définit uniquement les règles durables réellement propres à un langage, un écosystème, une plateforme, un framework, un type de projet ou un sous-système.
Les règles générales restent héritées implicitement. Elles ne sont pas recopiées dans chaque profil.
## Axes de spécialisation
La composition normative suit l'ordre général :
```text
GENERAL
↓
ecosystem / language
↓
platform
↓
framework
↓
project type / subsystem
↓
project-specific
↓
explicit exception
```
Cet ordre exprime la spécificité des scopes. Il ne signifie pas qu'un projet doit posséder un profil à chaque niveau.
Un projet peut par exemple combiner uniquement :
```text
GENERAL
+ Rust / Cargo
```
ou :
```text
GENERAL
+ Java
+ Gradle
+ Android
```
Une technologie absente du projet ne rend aucun profil correspondant applicable.
## Propriétaire normatif
Toute règle durable doit posséder un seul propriétaire normatif canonique.
Lorsqu'une règle est déjà correctement possédée par un document général, un profil spécifique doit la référencer si nécessaire, mais ne doit pas la recopier sous une formulation équivalente.
Inversement, une contrainte réellement propre à un profil ne doit pas être remontée vers un owner général uniquement pour réduire le nombre de fichiers.
Le propriétaire est choisi selon le scope le plus général dans lequel la règle reste vraie sans exception implicite.
## Applicabilité
Un profil doit rendre son scope explicite : l'utilisateur ou le skeleton futur doit pouvoir déterminer à partir de faits du projet si le profil s'applique.
L'applicabilité doit reposer sur des propriétés concrètes, par exemple :
- langage ou écosystème réellement utilisé ;
- build tool réellement utilisé ;
- plateforme réellement ciblée ;
- framework réellement présent ;
- type de projet ou sous-système réellement concerné.
PGR ne doit pas appliquer un profil uniquement parce qu'il est fréquent, recommandé ailleurs ou présent dans un projet source historique.
## Composition et résolution
La résolution d'un ensemble de profils suit ces étapes :
1. appliquer les règles générales ;
2. ajouter les profils langage/écosystème applicables ;
3. ajouter les profils plateforme applicables ;
4. ajouter les profils framework applicables ;
5. ajouter les profils de type de projet ou sous-système applicables ;
6. appliquer les règles propres au projet ;
7. appliquer les exceptions explicites et bornées.
Une règle plus spécifique peut raffiner, renforcer ou remplacer une règle plus générale dans son scope.
Lorsqu'elle contredit volontairement une règle héritée, le profil spécifique doit identifier l'override, son scope et sa raison. L'ordre des fichiers dans un répertoire ne crée jamais une priorité normative.
Deux règles applicables de même niveau qui se contredisent sans relation explicite ne sont pas départagées arbitrairement : la situation constitue un défaut de conformité ou de modélisation à résoudre.
## Spécialisation interne à une famille
Une famille peut posséder plusieurs niveaux internes lorsque cela réduit la duplication.
Par exemple, un profil de langage peut être complété par un build tool particulier :
```text
Java
↓
Maven
```
ou :
```text
Java
↓
Gradle
```
Cette relation interne ne modifie pas la hiérarchie globale. Une contrainte de plateforme plus spécifique peut encore raffiner le résultat lorsqu'elle s'applique.
Lorsque langage et build tool sont pratiquement indissociables pour le scope visé, PGR peut les documenter dans un même profil si cette fusion évite une séparation artificielle. Le choix du découpage doit suivre les responsabilités réelles, pas une taxonomie rigide.
## Baseline contrôlée et projet imposé
La même combinaison de technologies peut être gouvernée avec des degrés de liberté différents.
Pour une baseline créée et contrôlée par le projet, les profils sélectionnés s'appliquent intégralement puis une skeleton specification MAY fixer des choix réutilisables supplémentaires : layout, stack frontend, conventions de manifests ou organisation des fichiers.
Pour un projet existant ou imposé par un tiers, PGR doit d'abord préserver les contraintes externes réellement obligatoires. Toute divergence avec le profil préféré devient une règle project-specific ou une exception explicite et bornée ; elle ne modifie pas automatiquement le profil général.
Cette distinction évite deux erreurs opposées : forcer le skeleton interne d'une organisation sur un dépôt qu'elle ne contrôle pas, ou affaiblir ses propres conventions sous prétexte qu'un framework accepte plusieurs formes.
## Profils composites
PGR ne crée pas automatiquement un profil composite pour chaque combinaison possible.
Un profil composite n'est justifié que lorsque l'intersection de plusieurs profils possède des règles propres qui ne peuvent être correctement possédées par chacun séparément.
Ainsi, la simple coexistence de Rust et Android ne suffit pas à créer un profil `Rust + Android`. Un tel profil devient pertinent seulement lorsqu'un contrat propre à leur interaction, par exemple une frontière FFI/JNI, doit être normé.
## Choix ouverts
Un choix encore indécis n'est pas une règle.
Lorsqu'un profil révèle plusieurs options légitimes sans critère permettant d'en retenir une, PGR doit conserver la question comme décision ouverte, étude ou point de planification approprié plutôt que d'inventer une valeur par défaut arbitraire.
Une contrainte issue d'un framework, d'une plateforme ou d'un outil externe peut devenir une règle spécifique lorsque son caractère obligatoire est établi.
## Non-duplication
Un profil doit contenir uniquement ce qui ajoute une information normative dans son scope.
Il ne doit pas recopier les règles générales relatives notamment à la gouvernance, aux documents, aux secrets, au lifecycle des releases ou à la validation lorsque ces règles s'appliquent déjà sans modification.
Une règle transversale découverte pendant la création de plusieurs profils doit être remontée vers un propriétaire commun uniquement si elle est réellement indépendante de ces profils.
## Croissance documentaire
PGR matérialise uniquement les familles et profils possédant un contenu normatif réel.
Pour `0.0.2`, les familles nécessaires sont :
```text
500 — languages / ecosystems
600 — platforms
```
Les familles `700 — frameworks` et `800 — architecture` restent réservées tant qu'un premier profil réel ne justifie pas leur activation normative.
Le modèle architectural présent n'oblige pas à créer des fichiers placeholders pour les profils différés.
## Réconciliation des profils matérialisés en `0.0.2`
La première implémentation réelle du modèle comporte trois profils :
```text
510 — Rust / Cargo
520 — Java / Maven / Gradle
610 — Android
```
Leur composition observée confirme que la taxonomie n'a pas besoin d'un profil composite supplémentaire dans `0.0.2`.
Un projet Rust ordinaire peut appliquer :
```text
GENERAL
+ 500
+ 510
```
Un projet Java/Gradle Android peut appliquer :
```text
GENERAL
+ 500
+ 520
+ 600
+ 610
```
La forme condensée de cette composition est `GENERAL + 500 + 520 + 600 + 610`.
Le profil Android raffine localement les contraintes JDK/Gradle lorsque la matrice AGP/Gradle/JDK l'exige ; cette spécialisation ne modifie pas le profil Java/Gradle hors Android.
Aucune contradiction non résolue de même niveau n'a été identifiée entre les profils `510`, `520` et `610`.
La revue beta n'a pas justifié l'activation d'une famille `700 — frameworks` ou `800 — architecture`. Les règles réellement transversales rencontrées restent déjà possédées par `RULES.md`, les familles existantes ou le présent modèle architectural.
## Scission Java / Maven / Gradle en `0.1.2`
La réévaluation pratique de `0.1.2` confirme que le profil historique combiné `520 — Java / Maven / Gradle` ne constitue plus le meilleur owner courant. Maven et Gradle sont deux build tools interchangeables possédant chacun des règles propres significatives ; les rendre tous deux applicables par l'intermédiaire d'un unique profil Java crée une ambiguïté de sélection contraire au contrat de [`../rules/500-LANGUAGES.md`](../rules/500-LANGUAGES.md).
Le découpage courant devient :
```text
520 — Java
521 — Maven
522 — Gradle
```
Les spécialisations de build restent dans la famille `500` et se composent explicitement avec le langage réellement utilisé. Par exemple :
```text
GENERAL + 500 + 520 + 521
Java + Maven
GENERAL + 500 + 520 + 522
Java + Gradle
GENERAL + 500 + 520 + 522 + 600 + 610
Java + Gradle + Android
```
Un projet Gradle sans Java n'applique pas `520` uniquement parce qu'il utilise `522`. De même, Maven et Gradle ne sont jamais rendus applicables l'un par l'autre. Les contraintes Android restent possédées par `610` et raffinent `522`, ainsi que `520` uniquement lorsque Java est réellement présent.
Cette scission remplace l'owner courant combiné sans réécrire les documents historiques qui décrivent fidèlement l'état `0.0.2` à `0.1.1`. L'ancien chemin `520-JAVA_MAVEN_GRADLE.md` reste un bridge `SUPERSEDED` non normatif afin de préserver leurs liens.
## Réconciliation beta de Java / Maven / Gradle en `0.1.2`
La réconciliation `beta.1` confirme la scission introduite en `alpha.3` sans ajouter de quatrième owner ou d'artefact technique générique. Les owners courants restent :
```text
520 — Java
521 — Maven
522 — Gradle
```
Le corpus Games apporte une preuve pratique pour Java et Gradle, mais aucune preuve Maven réelle. Cette asymétrie ne remet pas en cause `521-MAVEN.md` : elle interdit seulement de présenter Games comme validation d'une convention Maven nouvelle ou de créer un artefact Maven à partir d'un corpus qui n'en possède pas.
La revue confirme également que les décisions locales Games ne deviennent pas des minima généraux : ni JDK 25, ni cible Java 17, ni Gradle 9.6.0+, ni Groovy DSL, ni absence de Wrapper ne sont imposés par les profils courants. Seuls les principes réutilisables démontrés sont conservés : séparation JDK/source/bytecode, ownership du build, contrainte système effectivement vérifiée et Wrapper conditionnel.
Aucun nouveau contrat sous `docs/validation/`, template, skeleton ou audit Python Java/Maven/Gradle n'est justifié. Les toolchains officielles restent propriétaires des preuves exécutables lorsque des artefacts Java/Maven/Gradle réels existent.
Enfin, Android reste un raffinement de plateforme : `610-ANDROID.md` possède AGP, SDK/NDK, ABI/JNI, manifests/resources, packaging/signing et smokes. La réconciliation `0.1.2` ne constitue pas le démarrage de `0.1.3`.
## Activation de la famille framework en `0.0.5`
La réconciliation indépendante de KSP et Games apporte le premier framework suffisamment répété pour activer la famille `700` : Tauri 2. Le profil `710-TAURI.md` se compose au-dessus de Rust/Cargo et, selon les targets, des profils plateforme applicables.
Cette activation ne change pas la hiérarchie : Tauri ne devient propriétaire ni des règles Rust générales, ni d'Android, ni du choix du frontend. Il possède uniquement l'orchestration Tauri, sa configuration/capabilities, ses hooks, sa version applicative et les gates d'intégration propres au framework.
La famille `800 — architecture` reste réservée : aucune règle nouvelle n'en justifie encore la matérialisation.
La réconciliation a également confirmé qu'une règle générale ne doit pas être recopiée comme si le profil spécifique en devenait propriétaire. Un profil peut rappeler une conséquence spécifique au contexte, mais doit référencer l'owner général lorsque le contrat lui-même n'est pas spécialisé.
## Owners frontend matérialisés en `0.1.1`
L'audit Games/KSP et la revue opérateur de `0.1.1-alpha.1` justifient quatre owners distincts dans la famille `500` :
```text
530 — TypeScript
540 — JavaScript package ecosystem
550 — Vite
560 — CSS / Sass
```
Cette séparation évite un profil monolithique « Web moderne » : TypeScript, Vite et Sass sont des recommandations fortes pour les nouveaux frontends contrôlés lorsqu'ils apportent une valeur proportionnée, mais chacun reste sélectionnable indépendamment. Le package manager est également indépendant et PGR n'impose pas npm.
Une composition complète peut par exemple être :
```text
GENERAL
+ 500
+ 530 TypeScript
+ 540 JavaScript package ecosystem
+ 550 Vite
+ 560 CSS / Sass
```
Un frontend minimal peut n'en sélectionner qu'une partie. Un host Tauri qui utilise cette stack ajoute ensuite `700 + 710` sans transférer à Tauri l'ownership des règles frontend :
```text
GENERAL + 500 + 510 + 530 + 540 + 550 + 560 + 700 + 710
```
WASM et serveur Web Rust restent des responsabilités séparées et ne sont pas activés par cette composition.
## Instanciation par skeleton
Les skeleton specifications sélectionnent les profils applicables et identifient les règles à reprendre ou adapter dans la baseline locale du projet créé. Leur contrat transversal de composition appartient à [`../rules/220-SKELETONS.md`](../rules/220-SKELETONS.md) ; le présent document reste propriétaire de la hiérarchie et de la résolution des profils eux-mêmes.
Le projet instancié reste autonome : la composition de profils sert à construire sa baseline initiale, pas à créer une dépendance dynamique vers PGR.

View File

@@ -0,0 +1,243 @@
<!-- file: docs/plans/002-V0_0_2_RULE_PROFILES_PLAN.md -->
<!-- version: 6 -->
# Plan 0.0.2 — premiers profils de règles technologiques
## Statut
Plan clôturé par la promotion stable `0.0.2` après validation de `0.0.2-rc.1.fix.1`.
La baseline `v0.0.1` est cohérente pour démarrer `0.0.2`. L'absence de `.git` dans cette archive est normale et n'est pas une anomalie de baseline.
Le présent plan reste prévisionnel. Il peut être révisé lorsqu'un résultat réel invalide son dimensionnement ou son découpage, conformément aux règles de REPLAN.
## Mission
`0.0.2` introduit les premiers profils de règles technologiques réutilisables de PGR sans dupliquer les responsabilités déjà possédées par `RULES.md` et les familles `200`, `300` et `400`.
La release doit démontrer concrètement la composition :
```text
GENERAL
↓
ecosystem / language
↓
platform
↓
framework
↓
project type / subsystem
↓
project-specific / explicit exception
```
Un profil matérialisé doit posséder un contenu normatif réel, un scope explicite et un propriétaire documentaire identifiable. Il ne doit pas devenir un catalogue de dépendances ni répéter les règles générales sous une autre forme.
## Autorité des sources pendant la consolidation
Pour cette release :
- l'archive source issue du tag `v0.0.1` est la baseline autoritaire de l'état PGR ;
- `prompts/002-V0_0_2_START_PROMPT.md` est le contrat opératoire de démarrage de `0.0.2` ;
- les corpus de conception externes ou historiques peuvent servir de matière d'analyse, mais ne constituent pas l'état courant du dépôt ;
- aucune règle, décision, version de fichier ou structure absente de la baseline et du prompt ne doit être supposée déjà acquise ;
- chaque proposition réutilisée doit être requalifiée selon les règles PGR actuelles avant de devenir normative.
## Audit de la baseline `v0.0.1`
L'inspection de l'archive taggée a constaté :
- une racine unique `pgr/` ;
- `44` fichiers et `13` répertoires dans l'archive, sans entrée dupliquée ;
- aucune entrée absolue, traversée `..` ou symlink ;
- aucune arborescence `.git`, conformément au contrat des archives de tag ;
- `VERSION` égal exactement à `0.0.1` ;
- aucun cache/build connu, `__pycache__`, `.pyc`, `node_modules`, `target`, `dist` ou secret local distribué ;
- tous les fichiers Markdown avec headers `file/version` cohérents avec leur emplacement ;
- aucun lien Markdown local cassé parmi les liens vérifiés ;
- `12` deltas `0.0.1` et `12` histories correspondants, sans delta ou history orphelin ;
- une chaîne de résultats cohérente : les `FAIL` de `alpha.1`, `alpha.1.fix.1`, `alpha.4` et `rc.1` restent historiques et sont suivis par leurs corrections validées avant progression ;
- la promotion `rel.001` enregistrée `PASS`, le plan `0.0.1` clôturé et le prompt `0.0.2` présent ;
- les compteurs internes `version:` des documents vivants cohérents avec les opérations `ADD`/`REPLACE` observées dans les deltas `0.0.1`.
Aucun défaut bloquant de gouvernance, de structure documentaire, de pairing delta/history ou de cohérence interne n'a été trouvé.
### Preuve post-tag `publish.001`
Le rapport post-tag `pgr-0.0.1-publish.001-report.md` a été retrouvé dans la bibliothèque de travail après la première revue de `alpha.1`.
Il enregistre `Status: PASS` pour `pgr-v0.0.1.zip` et confirme le SHA-256 déjà observé pour l'archive de baseline :
```text
48bfed6acc50d2c5bdd69db764ae29fe8c5a06b64375943f5d4120c7bb8429ef
```
Cette preuve est volontairement extérieure au tag `v0.0.1` parce qu'elle vérifie un artefact produit après le tag. Elle ne doit ni être injectée rétroactivement dans la stable ni remplacer l'audit d'intake de la session courante.
La revue a également identifié un besoin de maturité futur : un handoff/prompt de reprise doit finir par indiquer explicitement si une preuve post-publication telle que `publish.001` doit être fournie à la session suivante. Ce besoin de workflow reste hors scope fonctionnel de `0.0.2`.
## Inventaire des profils candidats
Le prompt demande d'examiner le corpus suivant. Après revue du sizing initial, `0.0.2-alpha.1.fix.1` réduit volontairement le nombre de profils matérialisés afin de conserver une version terminable et correctement validable dans une session.
| Domaine candidat | Décision `0.0.2` | Propriétaire prévisionnel | Motif |
|------------------------------------------------|------------------|------------------------------------------------|------------------------------------------------------------------------------|
| modèle de profil et composition des scopes | inclure | architecture PGR | nécessaire avant de créer plusieurs profils cohérents |
| Rust / Cargo | inclure | famille `500 — languages / ecosystems` | premier profil langage/écosystème, corpus éprouvé |
| Java / Maven / Gradle | inclure | famille `500 — languages / ecosystems` + build | permet de distinguer langage et build tool avant Android |
| Android | inclure | famille `600 — platforms` | premier exemple de spécialisation plateforme sur des règles de langage/build |
| Rust + Android / JNI | différer | future composition spécialisée | utile mais non nécessaire pour prouver le premier modèle |
| Web / TypeScript / Vite / WASM / serveurs Rust | différer | future composition Web | scope autonome suffisamment large pour une release ultérieure |
| Tauri desktop/mobile | différer | future famille `700 — frameworks` | dépend de profils Rust/Web/plateforme suffisamment stabilisés |
| C / C++ / CMake | différer | future famille `500 — languages / ecosystems` | corpus utile mais non nécessaire au premier lot |
| PHP / Composer | différer | future famille `500 — languages / ecosystems` | ne pas matérialiser un profil uniquement pour remplir la taxonomie |
| Python 3 application/package | différer | future famille `500 — languages / ecosystems` | à introduire lorsqu'un besoin concret le justifie |
| architecture/règles cross-cutting | conditionnel | famille `800 — architecture` ou owner existant | uniquement si plusieurs profils révèlent une règle commune sans propriétaire |
Les domaines différés restent des candidats légitimes. Leur absence de `0.0.2` ne vaut ni rejet ni interdiction future.
Le choix retenu cherche le plus petit ensemble qui exerce réellement plusieurs niveaux de composition : un modèle commun, un profil langage/écosystème, une distinction langage/build et une plateforme. Les compositions FFI, Web et framework restent séparées afin de ne pas transformer la première release de profils en catalogue.
## Règles de consolidation
Chaque tranche technologique doit :
1. repartir des règles générales actuellement applicables ;
2. identifier ce qui est réellement spécifique au profil ;
3. éviter les duplications de gouvernance, documentation et validation générales ;
4. distinguer règle normative, exemple, choix de projet et point encore ouvert ;
5. documenter explicitement les overrides/contraintes spécialisées et leur scope ;
6. préférer les structures canoniques de l'écosystème lorsqu'elles apportent une vraie valeur ;
7. ne pas fixer une version d'outil ou de dépendance sans raison de compatibilité, reproductibilité, support ou sécurité ;
8. ne créer un audit que lorsqu'une propriété stable, objectivement automatisable et réellement utile a été démontrée ;
9. conserver PGR lui-même indépendant des toolchains qu'il documente ;
10. réviser le plan si une tranche devient sensiblement plus large que prévu au lieu d'absorber silencieusement le scope.
## Découpage prévisionnel
### alpha.1 — Baseline audit and profile sizing
Auditer intégralement `v0.0.1`, confronter le prompt à l'état réel, inventorier les profils candidats, fixer les domaines inclus/différés et créer le présent plan.
Aucune règle technologique détaillée n'est consolidée dans cette tranche.
### alpha.2 — Rule profile model
Formaliser le contrat d'un profil PGR : ownership, composition général → spécifique, navigation des familles nécessaires, règles de non-duplication et traitement des choix encore ouverts.
Cette tranche doit créer uniquement les propriétaires documentaires réellement nécessaires à `0.0.2`. Les familles `700` et `800` restent réservées tant qu'aucun contenu réel ne justifie leur matérialisation.
### alpha.3 — Rust / Cargo
Consolider le premier profil langage/écosystème Rust/Cargo, notamment structure de workspace/crates, manifests et toolchain, dépendances/features, API/imports, erreurs/safety, tests et validation spécialisée lorsque ces sujets ne sont pas déjà possédés par une règle générale.
Cette tranche sert aussi de mesure réelle du coût d'un profil. Si elle montre que le modèle documentaire est sensiblement plus lourd que prévu, un REPLAN doit intervenir avant d'enchaîner les autres profils.
### alpha.4 — Java / Maven / Gradle
Consolider le profil Java et ses spécialisations de build Maven/Gradle en maintenant une frontière nette entre règles Java, contraintes de build tool et choix propres à une plateforme ou un framework.
### alpha.5 — Android
Consolider le premier profil plateforme Android : structure canonique, toolchain compatible, SDK/targets, configuration locale/signing, modules, packaging, tests/smokes et règles de compatibilité de target.
Les règles Rust/JNI, Web et Tauri ne doivent pas être absorbées dans ce profil général. Elles restent différées jusqu'à une release où leurs compositions pourront être traitées sans surcharger `0.0.2`.
### beta.1 — Profile reconciliation
Réconcilier les profils créés, vérifier les scopes/overrides, éliminer les répétitions, vérifier la navigation et extraire vers un owner cross-cutting uniquement les règles réellement communes qui ne possèdent pas déjà de propriétaire normatif.
Aucun nouveau profil technologique majeur ne doit être introduit en beta sans REPLAN.
État observé à l'entrée de beta :
```text
alpha.1 FAIL cadrage initial corrigé par fix.1
alpha.1.fix.1 PASS sizing réduit + premier audit Markdown
alpha.2 PASS modèle de profils et familles 500/600
alpha.3 PASS Rust / Cargo
alpha.4 FAIL incohérence locale entre texte et grep de gate
alpha.4.fix.1 PASS cohérence de gate rétablie
alpha.5 PASS Android
beta.1 FAIL quoting Bash invalide dans une commande de gate
beta.1.fix.1 PASS quoting de gate corrigé sans changement de scope
```
Cette synthèse décrit uniquement la trajectoire du plan ; les preuves détaillées restent dans les histories immuables correspondants.
La réconciliation beta confirme comme owners technologiques de `0.0.2` :
```text
510-RUST_CARGO.md
520-JAVA_MAVEN_GRADLE.md
610-ANDROID.md
```
Aucune famille `700` ou `800` n'est activée. Aucun profil différé n'est ramené dans le scope.
### rc.1 — Rule profiles release candidate
Geler le scope, préparer l'entrée candidate `0.0.2` du changelog, finaliser le prompt `0.0.3` et exécuter la gate documentaire complète applicable.
Le scope RC est gelé sur les trois profils matérialisés (`510`, `520`, `610`) et les deux audits génériques monotâches (`tables`, `liens locaux`). Aucun nouveau profil, owner de famille ou audit technologique n'est admis sans correction strictement nécessaire ou REPLAN.
Le prompt `0.0.3` doit aussi fournir explicitement le texte manuel de nouvelle session et indiquer le rôle du futur rapport post-tag `publish.001`, afin que cette information ne dépende plus d'une demande ad hoc de l'opérateur.
### stable — 0.0.2
Promouvoir mécaniquement la RC validée, finaliser les métadonnées de release, enregistrer `rel.001`, commit/tag `v0.0.2`, puis vérifier séparément l'archive publiée issue du tag.
## Clôture
La release candidate `rc.1` a été enregistrée `FAIL` à cause d'un audit Python inline invalide dans sa gate. `rc.1.fix.1` a corrigé exclusivement cette commande et a ensuite été validée `PASS`, sans changement du scope fonctionnel ou normatif.
La promotion stable `rel.001` clôt le plan en mettant à jour uniquement les métadonnées vivantes de release et en préparant le tag `v0.0.2`.
Le contrôle post-tag `publish.001` reste une preuve séparée : il doit vérifier l'archive réellement produite depuis le tag et fournir `pgr-0.0.2-publish.001-report.md` à la future session `0.0.3` lorsqu'il est `PASS`.
## Dimensionnement et points de replan
Le premier forecast `alpha.2` à `alpha.8` a été jugé trop large pendant la revue opérateur de `alpha.1`. Le présent plan réduit donc la release avant tout développement technologique lourd.
Après `alpha.1.fix.1`, le chemin prévu est :
```text
alpha.2 modèle de profil
alpha.3 Rust / Cargo
alpha.4 Java / Maven / Gradle
alpha.5 Android
beta.1 réconciliation
rc.1 release candidate
stable 0.0.2
```
Ce découpage reste un forecast, pas une obligation de remplir tous les numéros coûte que coûte.
`alpha.3` est un point de mesure explicite. Si la construction du premier profil montre qu'un profil complet dépasse sensiblement le sizing envisagé, la release doit être REPLANifiée avant `alpha.4` au lieu de conserver mécaniquement le forecast.
Un nouveau besoin critique, plusieurs fixes consécutifs ou une évolution qui rend `0.0.2` non terminable dans la session doivent également déclencher un REPLAN. La qualité de la release prend le dessus sur la volonté de conserver artificiellement le nombre initial de profils.
## Hors périmètre
`0.0.2` ne doit pas :
- produire les templates techniques réservés à `0.0.3` ;
- créer les skeleton specifications complètes réservées à `0.0.4` ;
- créer un générateur ;
- réécrire KSP ou `sasedev-games` ;
- multiplier les audits spécialisés ; `0.0.2` ne matérialise que des audits génériques monotâches justifiés par un besoin réel (`tables` puis `liens locaux`), sans audit technologique artificiel ;
- transformer les exemples de technologies en dépendances du dépôt PGR ;
- modifier rétroactivement les deltas/histories `0.0.1` pour refléter des règles apparues après leur émission.
## Critères de fermeture
`0.0.2` peut atteindre RC lorsque :
- le modèle documentaire des profils est explicite et cohérent avec la hiérarchie PGR ;
- les profils retenus dans le scope possèdent chacun un propriétaire normatif réel ;
- les spécialisations de build et de plateforme retenues ne contaminent pas les règles générales ;
- les choix encore ouverts restent identifiés comme tels ;
- la navigation entre règles générales et profils spécifiques est claire ;
- aucune duplication importante avec les familles `200`, `300` et `400` ne subsiste ;
- les profils différés ne sont pas artificiellement matérialisés ;
- les validations de la release restent documentaires et proportionnées au dépôt PGR lui-même.

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