# 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 '' docs/validation/003-RUST_EXPORT_COMPLETENESS.md grep -Fx '' 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é.