Files
pgr/deltas/0.1.0/alpha.5.md
2026-09-26 20:33:53 +02:00

14 KiB
Raw Blame History

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 :

0.1.0-alpha.4

Version après application :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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 :

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.