diff --git a/Cargo.toml b/Cargo.toml index 508b6e6..04ae8d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 161 +# version: 162 [workspace] resolver = "3" members = ["crates/ksp-app-config-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"] [workspace.package] -version = "0.2.5-pre.10.fix.2" +version = "0.2.5-pre.10.fix.3" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/deltas/0.2.5/pre.010-fix.003.md b/deltas/0.2.5/pre.010-fix.003.md new file mode 100644 index 0000000..0e45967 --- /dev/null +++ b/deltas/0.2.5/pre.010-fix.003.md @@ -0,0 +1,133 @@ + + + +# Delta `0.2.5-pre.010-fix.003` — alignement audit Rust sur rustfmt et TODO prix offchain + +## 1. Base et version + +Base : + +```text +0.2.5-pre.010-fix.002 +workspace.package.version = 0.2.5-pre.10.fix.2 +``` + +Version technique cible : + +```text +workspace.package.version = 0.2.5-pre.10.fix.3 +``` + +Identifiant de livraison : + +```text +0.2.5-pre.010-fix.003 +``` + +Commit attendu après validation : + +```text +v0.2.5-pre.010-fix.003 +``` + +Aucun tag stable n'est créé par ce fix et `rel.001` reste bloqué jusqu'à validation complète. + +## 2. Cause du fix + +Après application de `fix.002`, l'opérateur a exécuté la séquence canonique : + +```bash +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +``` + +`cargo fmt` a produit un ordre valide et canonique dans les façades, mais l'audit Python a ensuite signalé 52 violations `RUST-FMT-107` parce qu'il imposait son propre tri alphabétique par **symbole exporté**. + +Ce contrôle était incorrect : l'audit structurel ne doit pas réimplémenter un ordre de réexports différent de celui possédé par rustfmt. + +Les contrôles Rust/Cargo du même checkpoint étaient par ailleurs verts : `cargo check --workspace`, Clippy, tests Wallet et tests workspace complets passent. + +## 3. Correction de l'audit des réexports + +`RUST-FMT-107` est retiré de `audit_rust_general_rules.py`. + +Le script continue de vérifier les contraintes structurelles que rustfmt ne possède pas : + +```text +pub use avant pub(crate) use +exactement une ligne vide entre les deux visibilités +aucune ligne vide à l'intérieur d'un bloc homogène +pas de grouped use/re-export +pas de glob +pas d'alias +réexports internes via self:: +rustdoc adjacente +résolution crate-root via l'audit de complétude +``` + +En revanche, l'ordre intra-bloc des `use`/réexports est désormais explicitement délégué à : + +```bash +cargo fmt --all +``` + +Le script ne tente plus de trier par symbole exporté ni de reproduire l'algorithme de rustfmt. + +## 4. Règles Rust synchronisées + +`RULES_RUST.md` précise désormais que : + +- `rustfmt.toml` et `cargo fmt --all` sont canoniques pour l'ordre interne des `use`/réexports ; +- `RUST-FMT-005` n'impose pas son tri générique aux `use`/réexports ; +- `RUST-FMT-007` ne possède que la structure `pub` / `pub(crate)` et l'espacement ; +- `RUST-AUDIT-003` interdit explicitement au script de réimplémenter un ordre concurrent à rustfmt. + +## 5. TODO `0.2.11` ajouté au prompt `0.2.6` + +Le prompt `prompts/011-V0_2_6_START_PROMPT.md` contient maintenant un TODO durable : + +```text +0.2.11 + après réalisation et validation de l'application spécialisée de visualisation + de prix offchain, intégrer cette capacité dans ksp-app-wallet-desk +``` + +Le TODO précise que `0.2.6` ne doit pas anticiper cette logique et que `0.2.11` devra réauditer la frontière de partage afin de ne pas dupliquer récupération, normalisation, cache ou contrats de prix dans Wallet Desk. + +## 6. Périmètre + +Ce fix ne modifie : + +```text +aucun fichier Rust +aucune API runtime +aucun wire .kspwallet +aucune dépendance +aucune primitive cryptographique +``` + +Le bump Cargo est requis parce que le script d'audit fait partie du toolchain de validation technique KSP. + +## 7. Validation de préparation + +Les scripts Python modifiés doivent passer : + +```bash +python3 -m py_compile scripts/audit_rust_general_rules.py +python3 scripts/audit_rust_workspace_rules.py +``` + +La validation opérateur canonique doit impérativement conserver `cargo fmt --all` **avant** l'audit structurel afin de vérifier que le script accepte exactement l'état formaté par rustfmt. + +## 8. Validation opérateur requise + +```bash +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +cargo check --workspace +cargo clippy --workspace --all-targets +cargo test -p ksp-wallet-lib +cargo test --workspace +``` + +Les arbres de dépendances ne nécessitent pas d'être répétés pour ce fix : aucune dépendance n'est modifiée. diff --git a/docs/rules/RULES_RUST.md b/docs/rules/RULES_RUST.md index f3f556c..65a3438 100644 --- a/docs/rules/RULES_RUST.md +++ b/docs/rules/RULES_RUST.md @@ -1,5 +1,5 @@ - + # Règles Rust générales @@ -55,9 +55,9 @@ Les règles `RUST-*` s'appliquent à tous les fichiers Rust de KSP : crates, sou - **RUST-FMT-002** — `cargo fmt --all` est exécuté après chaque modification Rust avant l'audit structurel et les validations Cargo. - **RUST-FMT-003** — Aucune ligne vide n'est conservée à l'intérieur du corps d'une fonction ou méthode, ni à l'intérieur d'une définition `struct` ou `enum`. - **RUST-FMT-004** — Deux fonctions ou méthodes distinctes, y compris deux `const fn`, sont séparées par exactement une ligne vide. La même séparation exacte s'applique entre `struct`, `enum`, `union`, `trait`, bloc `impl` et fonction/méthode lorsqu'ils constituent des items voisins d'un même scope. -- **RUST-FMT-005** — Les blocs homogènes sont ordonnés alphabétiquement par nom lorsque l'ordre n'a pas de signification sémantique. +- **RUST-FMT-005** — Les blocs homogènes sont ordonnés alphabétiquement par nom lorsque l'ordre n'a pas de signification sémantique. Cette règle ne redéfinit pas l'ordre interne des `use`/réexports : pour ceux-ci, la sortie de `cargo fmt --all` est canonique. - **RUST-FMT-006** — Les constantes de module ou associées sont ordonnées par visibilité `pub`, puis `pub(crate)`, puis privée, et alphabétiquement dans chaque niveau. Deux constantes de même visibilité appartenant au même bloc ne sont séparées par aucune ligne vide ; exactement une ligne vide sépare deux niveaux de visibilité distincts. -- **RUST-FMT-007** — Dans une façade, le bloc `pub use` précède le bloc `pub(crate) use`; une seule ligne vide sépare les deux blocs, aucune ligne vide n'existe à l'intérieur d'un bloc, et les symboles sont ordonnés alphabétiquement. +- **RUST-FMT-007** — Dans une façade, le bloc `pub use` précède le bloc `pub(crate) use`; une seule ligne vide sépare les deux blocs et aucune ligne vide n'existe à l'intérieur d'un bloc. L'ordre intra-bloc des `use`/réexports est celui produit par `cargo fmt --all`; l'audit Python ne lui substitue aucun tri concurrent par symbole exporté ou chemin source. - **RUST-FMT-008** — Les déclarations `mod` d'un même bloc sont ordonnées alphabétiquement ; les modules de tests conditionnels restent après les modules de production. - **RUST-FMT-009** — Lorsqu'un `struct` et ses blocs `impl` forment une unité locale sans contrainte de séparation, l'implémentation suit la structure. Les éléments visibles précèdent les helpers privés lorsqu'aucun ordre métier ou protocolaire n'impose l'inverse. - **RUST-FMT-010** — L'ordre alphabétique n'écrase jamais un ordre contractuel ou sémantique : wire fields, comptes Solana, étapes de protocole, priorités, transitions d'état, tableaux de dispatch et séquences explicitement normatives conservent leur ordre défini. @@ -102,7 +102,7 @@ Les règles `RUST-*` s'appliquent à tous les fichiers Rust de KSP : crates, sou - **RUST-AUDIT-001** — `scripts/audit_rust_workspace_rules.py` est le point d'entrée obligatoire de l'audit Rust KSP. Il exécute les audits généraux, la complétude des réexports/chemins et les frontières KSP sans fusionner leurs responsabilités. - **RUST-AUDIT-002** — L'audit est dependency-free côté Python standard et échoue avec un code non nul dès qu'une violation mécanique est détectée. -- **RUST-AUDIT-003** — L'audit contrôle au minimum : headers/version/newline, lints de crate-root, visibilité interdite, `use`/aliases/groupes/globs/scope, rustdocs visibles, ordre des imports/réexports/constantes, lignes vides dans fonctions/structs/enums, complétude des réexports crate-root, chemins `crate::module::Item`, usage de `super::` dans les tests séparés et frontières KSP directement vérifiables. +- **RUST-AUDIT-003** — L'audit contrôle au minimum : headers/version/newline, lints de crate-root, visibilité interdite, `use`/aliases/groupes/globs/scope, rustdocs visibles, structure des blocs de réexports, ordre des imports de traits et constantes lorsque KSP le possède, lignes vides dans fonctions/structs/enums, complétude des réexports crate-root, chemins `crate::module::Item`, usage de `super::` dans les tests séparés et frontières KSP directement vérifiables. L'ordre intra-bloc des `use`/réexports reste la responsabilité canonique de `cargo fmt --all` et n'est pas réimplémenté par le script. - **RUST-AUDIT-004** — Les règles contextuelles qui ne peuvent pas être prouvées sans interpréter la sémantique restent des critères de revue humaine ; le script ne doit pas produire de faux sentiment de complétude. ## Contrôle avant livraison diff --git a/prompts/011-V0_2_6_START_PROMPT.md b/prompts/011-V0_2_6_START_PROMPT.md index 15cf234..a6d49e3 100644 --- a/prompts/011-V0_2_6_START_PROMPT.md +++ b/prompts/011-V0_2_6_START_PROMPT.md @@ -1,5 +1,5 @@ - + # Prompt de démarrage `0.2.6` — Wallet Desk @@ -668,6 +668,12 @@ trading Le Wallet Desk valide et administre Wallet ; il ne devient pas l'application globale KSP. +### TODO futur `0.2.11` — prix offchain dans Wallet Desk + +La visualisation de prix offchain n'appartient pas au scope de `0.2.6`. Une application spécialisée de visualisation de prix offchain doit d'abord être réalisée et valider durablement ses sources, contrats, rafraîchissement, cache et UX. + +Pour `0.2.11`, prévoir explicitement un chantier d'intégration de cette capacité dans `ksp-app-wallet-desk` afin qu'un wallet puisse afficher les informations de prix offchain pertinentes sans dupliquer la logique de récupération/normalisation possédée par le composant spécialisé. Le futur travail devra réauditer la frontière entre application, bibliothèque/service partagé et Transport avant implémentation ; le TODO n'autorise pas l'ajout anticipé de logique de prix dans Wallet Desk pendant `0.2.6`. + ## 25. Résultat attendu de `0.2.6` À la clôture stable : diff --git a/scripts/audit_rust_general_rules.py b/scripts/audit_rust_general_rules.py index 1343b94..5df536f 100644 --- a/scripts/audit_rust_general_rules.py +++ b/scripts/audit_rust_general_rules.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # file: scripts/audit_rust_general_rules.py -# version: 4 +# version: 5 """Audit mechanically verifiable Rust normalization rules used by KSP.""" @@ -186,13 +186,6 @@ def preceding_doc_line(lines: list[str], index: int) -> bool: return cursor >= 0 and lines[cursor].lstrip().startswith("///") -def export_symbol(line: str) -> str: - """Return the re-exported symbol name from one ungrouped re-export.""" - - path = line.split(" use ", 1)[1].split(";", 1)[0].strip() - return path.rsplit("::", 1)[-1] - - def natural_key(value: str) -> tuple[tuple[int, object], ...]: """Return a natural case-sensitive ordering key.""" @@ -523,12 +516,12 @@ def audit_file(root: pathlib.Path, path: pathlib.Path) -> list[Violation]: for attribute in ("#![warn(missing_docs)]", "#![deny(unreachable_pub)]", "#![forbid(unsafe_code)]"): if attribute not in lines[:24]: violations.append(Violation("RUST-BASE-103", relative, 1, f"missing `{attribute}`")) - exports: list[tuple[int, str, str]] = [] + exports: list[tuple[int, str]] = [] for idx, line in enumerate(lines, 1): stripped = line.strip() if stripped.startswith("pub use ") or stripped.startswith("pub(crate) use "): visibility = "pub(crate)" if stripped.startswith("pub(crate) use ") else "pub" - exports.append((idx, visibility, export_symbol(stripped))) + exports.append((idx, visibility)) if not preceding_doc_line(lines, idx): violations.append(Violation("RUST-DOC-102", relative, idx, "crate-root re-export requires adjacent rustdoc")) source_match = re.match(r"^pub(?:\(crate\))?\s+use\s+(?:self::)?([A-Za-z_][A-Za-z0-9_]*)::", stripped) @@ -544,22 +537,21 @@ def audit_file(root: pathlib.Path, path: pathlib.Path) -> list[Violation]: if blank_count != 1: violations.append(Violation("RUST-FMT-113", relative, crate_start, f"pub use and pub(crate) use blocks require exactly one blank line; found {blank_count}")) crate_seen = False - previous_by_visibility: dict[str, tuple[int, str]] = {} - for idx, visibility, symbol in exports: + previous_by_visibility: dict[str, int] = {} + for idx, visibility in exports: if visibility == "pub(crate)": crate_seen = True elif crate_seen: violations.append(Violation("RUST-FMT-105", relative, idx, "pub use block must precede pub(crate) use block")) - previous = previous_by_visibility.get(visibility) - if previous is not None: - previous_idx, previous_symbol = previous + previous_idx = previous_by_visibility.get(visibility) + if previous_idx is not None: # One homogeneous block may contain rustdocs but no blank line. + # rustfmt is authoritative for intra-block re-export ordering; + # this audit must not impose a competing exported-symbol sort. between = lines[previous_idx:idx - 1] if any(not candidate.strip() for candidate in between): violations.append(Violation("RUST-FMT-106", relative, idx, f"{visibility} use block contains an empty line")) - if natural_key(symbol) < natural_key(previous_symbol): - violations.append(Violation("RUST-FMT-107", relative, idx, f"{visibility} use block is not alphabetically ordered by exported symbol")) - previous_by_visibility[visibility] = (idx, symbol) + previous_by_visibility[visibility] = idx violations.extend(audit_blank_lines_in_bodies(relative, lines, masked_lines, depths)) violations.extend(audit_item_spacing_and_nesting(relative, lines, masked_lines, depths)) violations.extend(audit_module_order(relative, lines, depths))