Files
pgr/deltas/0.0.5/alpha.5.fix.1.md

7.5 KiB

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 :

0.0.5-alpha.5

Version après application :

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 :

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 :

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 :

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 :

crate::Item

Le diagnostic couvre désormais les formes suivantes lorsqu'elles désignent cet item partagé :

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 :

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 :

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 :

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é.