v0.3.6-pre.002-fix.001

This commit is contained in:
2026-09-01 10:55:35 +02:00
parent a25d8dd55a
commit cb670952e8
5 changed files with 124 additions and 16 deletions

View File

@@ -1,12 +1,12 @@
# file: Cargo.toml # file: Cargo.toml
# version: 395 # version: 396
[workspace] [workspace]
resolver = "3" resolver = "3"
members = ["crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib"] members = ["crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib"]
[workspace.package] [workspace.package]
version = "0.3.6-pre.2" version = "0.3.6-pre.2.fix.1"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"

View File

@@ -1,7 +1,7 @@
// file: crates/ksp-job-api/unit_tests/lifecycle.rs // file: crates/ksp-job-api/unit_tests/lifecycle.rs
// version: 1 // version: 2
fn lifecycle() -> std::option::Option<crate::JobLifecycle> { fn new_lifecycle() -> std::option::Option<crate::JobLifecycle> {
let id = match crate::JobId::new("job-001") { let id = match crate::JobId::new("job-001") {
std::result::Result::Ok(value) => value, std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None, std::result::Result::Err(_) => return std::option::Option::None,
@@ -16,7 +16,7 @@ fn lifecycle() -> std::option::Option<crate::JobLifecycle> {
#[test] #[test]
fn pre_002_lifecycle_accepts_every_planned_terminal_path() { fn pre_002_lifecycle_accepts_every_planned_terminal_path() {
for completion in [crate::JobCompletion::Complete, crate::JobCompletion::Partial] { for completion in [crate::JobCompletion::Complete, crate::JobCompletion::Partial] {
let lifecycle = lifecycle(); let lifecycle = new_lifecycle();
assert!(lifecycle.is_some()); assert!(lifecycle.is_some());
let mut lifecycle = match lifecycle { let mut lifecycle = match lifecycle {
std::option::Option::Some(value) => value, std::option::Option::Some(value) => value,
@@ -28,7 +28,7 @@ fn pre_002_lifecycle_accepts_every_planned_terminal_path() {
assert!(lifecycle.state().is_terminal()); assert!(lifecycle.state().is_terminal());
assert_eq!(lifecycle.state().completion(), std::option::Option::Some(completion)); assert_eq!(lifecycle.state().completion(), std::option::Option::Some(completion));
} }
let lifecycle = lifecycle(); let lifecycle = new_lifecycle();
assert!(lifecycle.is_some()); assert!(lifecycle.is_some());
let mut lifecycle = match lifecycle { let mut lifecycle = match lifecycle {
std::option::Option::Some(value) => value, std::option::Option::Some(value) => value,
@@ -37,7 +37,7 @@ fn pre_002_lifecycle_accepts_every_planned_terminal_path() {
assert!(lifecycle.start().is_ok()); assert!(lifecycle.start().is_ok());
assert!(lifecycle.fail().is_ok()); assert!(lifecycle.fail().is_ok());
assert_eq!(lifecycle.state(), crate::JobState::Failed); assert_eq!(lifecycle.state(), crate::JobState::Failed);
let lifecycle = lifecycle(); let lifecycle = new_lifecycle();
assert!(lifecycle.is_some()); assert!(lifecycle.is_some());
let mut lifecycle = match lifecycle { let mut lifecycle = match lifecycle {
std::option::Option::Some(value) => value, std::option::Option::Some(value) => value,
@@ -51,7 +51,7 @@ fn pre_002_lifecycle_accepts_every_planned_terminal_path() {
#[test] #[test]
fn pre_002_cancelling_allows_cancel_complete_or_fail() { fn pre_002_cancelling_allows_cancel_complete_or_fail() {
for terminal in [crate::JobState::Cancelled, crate::JobState::Completed(crate::JobCompletion::Complete), crate::JobState::Failed] { for terminal in [crate::JobState::Cancelled, crate::JobState::Completed(crate::JobCompletion::Complete), crate::JobState::Failed] {
let lifecycle = lifecycle(); let lifecycle = new_lifecycle();
assert!(lifecycle.is_some()); assert!(lifecycle.is_some());
let mut lifecycle = match lifecycle { let mut lifecycle = match lifecycle {
std::option::Option::Some(value) => value, std::option::Option::Some(value) => value,
@@ -73,7 +73,7 @@ fn pre_002_cancelling_allows_cancel_complete_or_fail() {
#[test] #[test]
fn pre_002_invalid_transition_preserves_source_state_and_reports_safe_context() { fn pre_002_invalid_transition_preserves_source_state_and_reports_safe_context() {
let lifecycle = lifecycle(); let lifecycle = new_lifecycle();
assert!(lifecycle.is_some()); assert!(lifecycle.is_some());
let mut lifecycle = match lifecycle { let mut lifecycle = match lifecycle {
std::option::Option::Some(value) => value, std::option::Option::Some(value) => value,
@@ -99,7 +99,7 @@ fn pre_002_invalid_transition_preserves_source_state_and_reports_safe_context()
fn pre_002_every_terminal_state_rejects_later_mutation() { fn pre_002_every_terminal_state_rejects_later_mutation() {
let terminals = [crate::JobState::Completed(crate::JobCompletion::Complete), crate::JobState::Cancelled, crate::JobState::Failed]; let terminals = [crate::JobState::Completed(crate::JobCompletion::Complete), crate::JobState::Cancelled, crate::JobState::Failed];
for terminal in terminals { for terminal in terminals {
let lifecycle = lifecycle(); let lifecycle = new_lifecycle();
assert!(lifecycle.is_some()); assert!(lifecycle.is_some());
let mut lifecycle = match lifecycle { let mut lifecycle = match lifecycle {
std::option::Option::Some(value) => value, std::option::Option::Some(value) => value,

View File

@@ -0,0 +1,99 @@
<!-- file: deltas/0.3.6/pre.002-fix.001.md -->
<!-- version: 1 -->
# Delta `0.3.6-pre.002-fix.001` — compilation des tests lifecycle
## Base requise
```text
0.3.6-pre.002
workspace.package.version = 0.3.6-pre.2
SHA-256 archive = d49f551ce2c04aeb3b545bfc11f0d66852ca10fd75b65c8614a8b99a3eb6cb0f
```
## Objectif
Corriger strictement l'erreur de compilation découverte par le gate opérateur dans `unit_tests/lifecycle.rs`, sans modifier l'API publique, le lifecycle, le token d'annulation ni le périmètre fonctionnel de `pre.002`.
## Défaut observé
Le premier test créait une variable locale nommée `lifecycle`, puis tentait plus bas de rappeler le helper homonyme `lifecycle()`. Le binding local masquait alors la fonction et provoquait `E0618`; l'inférence qui suivait produisait également `E0282`.
`cargo check --workspace` était vert parce qu'il ne compilait pas les modules `#[cfg(test)]`. Clippy `--all-targets` et `cargo test -p ksp-job-api` ont correctement exposé le défaut.
## Correction
Le helper privé de fixture devient `new_lifecycle()` et ses six appels sont synchronisés. Le nom distinct ne peut plus être masqué par les variables `lifecycle` représentant les instances testées. Les dix tests unitaires et onze canaries d'intégration restent inchangés en nombre et en intention.
## Fichiers ajoutés
```text
deltas/0.3.6/pre.002-fix.001.md
```
## Fichiers modifiés
```text
Cargo.toml
crates/ksp-job-api/unit_tests/lifecycle.rs
docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md
docs/validation/023-V0_3_6_JOB_API_BACKFILL.md
```
Mécanique Cargo :
```text
header version: 395 -> 396
workspace.package.version: 0.3.6-pre.2 -> 0.3.6-pre.2.fix.1
```
Le bump est obligatoire car le correctif modifie un fichier Rust compilé par les tests.
## Fichiers supprimés
Aucun.
## Décisions prises
- conserver la fixture commune et lui donner un nom non ambigu ;
- ne pas réécrire les tests ni élargir leur périmètre dans ce fix ;
- conserver exactement la surface publique et la matrice de transitions de `pre.002` ;
- ne pas ouvrir les notifications de `pre.003` avant un gate opérateur vert.
## Validations exécutées
```text
python3 scripts/audit_rust_workspace_rules.py
-> General Rust rule audit: clean
-> Rust export completeness audit: 0 candidate(s)
-> KSP workspace Rust rule audit: clean
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.6
-> Markdown table audit: clean (264 tables / 143 fichiers)
python3 -m unittest scripts/tests/test_audit_markdown_tables.py
-> 5 tests / OK
```
La reconstruction de la base et la comparaison différentielle confirment que seuls les cinq fichiers listés appartiennent au correctif.
## Validations non exécutées
L'environnement d'assemblage ne fournit ni `cargo` ni `rustfmt`. Les commandes Rust restent à rejouer par l'opérateur ; elles ne sont pas annoncées comme réussies dans ce delta.
## Gate opérateur demandé
```bash
cargo fmt --all
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.6
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-job-api
cargo tree -p ksp-job-api --edges normal
cargo tree -p ksp-job-api -e features
```
## Questions ouvertes
Aucune question ne bloque `pre.003` après un gate opérateur vert.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md --> <!-- file: docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md -->
<!-- version: 3 --> <!-- version: 4 -->
# Plan v0.3.6 — Job API et premier backfill RAW # Plan v0.3.6 — Job API et premier backfill RAW
@@ -392,11 +392,17 @@ Le sizing tabulaire est remplacé par les présentes sous-sections afin que chaq
### `pre.002` — Identité, lifecycle et annulation Job API ### `pre.002` — Identité, lifecycle et annulation Job API
**Statut : matérialisé ; audits statiques propres, gate Cargo opérateur à exécuter.** **Statut : alisé ; corrigé par `pre.002-fix.001`.**
Budget cible : **15-20 min**. Entrée : plan 027 corrigé, gate Markdown fiable et `cargo check --workspace` opérateur vert sur `pre.001-fix.001`. La crate `ksp-job-api` est ajoutée avec `JobId`, `JobKindCode`, `JobCompletion`, `JobState`, `JobLifecycle` et `JobCancellationToken`. Les identités utilisent un alphabet sûr et une borne de 128 octets ; leur valeur est privée et `JobId` est redacted en `Debug`. Le lifecycle possédé n'est pas cloneable, n'autorise que les transitions décidées et conserve les terminaux immuables. Le token partage un `AtomicBool` par `Arc`, rend la première demande observable et reste indépendant de tout runtime. Budget cible : **15-20 min**. Entrée : plan 027 corrigé, gate Markdown fiable et `cargo check --workspace` opérateur vert sur `pre.001-fix.001`. La crate `ksp-job-api` est ajoutée avec `JobId`, `JobKindCode`, `JobCompletion`, `JobState`, `JobLifecycle` et `JobCancellationToken`. Les identités utilisent un alphabet sûr et une borne de 128 octets ; leur valeur est privée et `JobId` est redacted en `Debug`. Le lifecycle possédé n'est pas cloneable, n'autorise que les transitions décidées et conserve les terminaux immuables. Le token partage un `AtomicBool` par `Arc`, rend la première demande observable et reste indépendant de tout runtime.
La tranche ajoute dix tests unitaires et onze canaries d'intégration réparties entre API publique, dépendances, complétude et sécurité. Les audits Rust/Markdown locaux sont propres ; `cargo`, `rustfmt`, Clippy et les tests Rust ne sont pas disponibles dans l'environnement d'assemblage. La sortie exige donc encore le gate opérateur `cargo fmt`, `cargo check`, Clippy et `cargo test -p ksp-job-api`. Aucune notification, séquence, snapshot, crate Backfill, dépendance Logging/Transport/Store ou surface Worker n'est ouverte. La tranche ajoute dix tests unitaires et onze canaries d'intégration réparties entre API publique, dépendances, complétude et sécurité. Le gate opérateur a confirmé `cargo fmt`, les audits, `cargo check --workspace` et les deux arbres Cargo. Clippy `--all-targets` et `cargo test -p ksp-job-api` ont toutefois révélé que le helper de fixture `lifecycle()` était masqué par une variable locale homonyme dans un test unitaire. Aucune notification, séquence, snapshot, crate Backfill, dépendance Logging/Transport/Store ou surface Worker n'est ouverte.
#### `pre.002-fix.001` — Compilation des tests lifecycle
**Statut : matérialisé ; gate Cargo opérateur à rejouer.**
Le helper de fixture est renommé `new_lifecycle()` et tous ses appels sont synchronisés afin d'éliminer le masquage lexical à l'origine des erreurs Rust `E0618` et `E0282`. Le correctif ne modifie ni l'API publique, ni les transitions, ni le nombre de tests. Comme un fichier Rust est corrigé, la version workspace devient `0.3.6-pre.2.fix.1`.
### `pre.003` — Notifications latest-value génériques ### `pre.003` — Notifications latest-value génériques

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/023-V0_3_6_JOB_API_BACKFILL.md --> <!-- file: docs/validation/023-V0_3_6_JOB_API_BACKFILL.md -->
<!-- version: 3 --> <!-- version: 4 -->
# Validation v0.3.6 — Job API et premier backfill RAW # Validation v0.3.6 — Job API et premier backfill RAW
@@ -46,6 +46,9 @@ Aucune entrée absolue, traversée, avec séparateur inversé ou lien symbolique
- [X] Contrats et tailles des trois nouveaux fichiers vérifiés. - [X] Contrats et tailles des trois nouveaux fichiers vérifiés.
- [X] Le journal opérateur fourni rapporte `cargo fmt`, audits, `cargo check`, `cargo clippy` et suites Interface ou Program verts sur v0.3.5. - [X] Le journal opérateur fourni rapporte `cargo fmt`, audits, `cargo check`, `cargo clippy` et suites Interface ou Program verts sur v0.3.5.
- [X] Gate opérateur de `pre.001-fix.001` : 5 tests Python, audit Markdown 264/141, audit Rust et `cargo check --workspace` verts. - [X] Gate opérateur de `pre.001-fix.001` : 5 tests Python, audit Markdown 264/141, audit Rust et `cargo check --workspace` verts.
- [X] Gate opérateur de `pre.002` : `cargo fmt`, audits Rust/Markdown, `cargo check --workspace` et arbres Cargo normal/features verts.
- [X] Échec de `pre.002` constaté dans la preuve opérateur : Clippy `--all-targets` et les tests compilent `unit_tests/lifecycle.rs`, où le helper `lifecycle()` est masqué par une variable homonyme (`E0618`, puis `E0282`).
- [X] `pre.002-fix.001` renomme uniquement le helper en `new_lifecycle()` et synchronise ses six appels sans modifier le contrat public ni la matrice de transitions.
- [X] L'environnement courant ne fournit pas l'exécutable `cargo` ; aucune validation Rust locale n'est annoncée comme exécutée. - [X] L'environnement courant ne fournit pas l'exécutable `cargo` ; aucune validation Rust locale n'est annoncée comme exécutée.
- [X] Le workspace compte 14 crates et aucune crate Job au point de départ. - [X] Le workspace compte 14 crates et aucune crate Job au point de départ.
@@ -176,8 +179,8 @@ Aucune entrée absolue, traversée, avec séparateur inversé ou lien symbolique
- [ ] Aucun retour de dépendance vers Job depuis les couches basses. - [ ] Aucun retour de dépendance vers Job depuis les couches basses.
- [ ] Versions et features des nouvelles dépendances auditées avant ajout. - [ ] Versions et features des nouvelles dépendances auditées avant ajout.
- [ ] `cargo fmt --all -- --check` vert. - [ ] `cargo fmt --all -- --check` vert.
- [X] `scripts/audit_rust_workspace_rules.py` vert sur `pre.002` dans l'environnement d'assemblage. - [X] `scripts/audit_rust_workspace_rules.py` vert sur `pre.002-fix.001` dans l'environnement d'assemblage.
- [X] `scripts/audit_markdown_tables.py` vert sur `pre.002` dans l'environnement d'assemblage. - [X] `scripts/audit_markdown_tables.py` vert sur `pre.002-fix.001` dans l'environnement d'assemblage.
- [X] Contrats de fichiers de `FILE_CONTRACTS.md` vérifiés sur chaque ajout de `pre.001`. - [X] Contrats de fichiers de `FILE_CONTRACTS.md` vérifiés sur chaque ajout de `pre.001`.
- [ ] `cargo check --workspace` vert. - [ ] `cargo check --workspace` vert.
- [ ] `cargo clippy --workspace --all-targets --all-features -- -D warnings` vert. - [ ] `cargo clippy --workspace --all-targets --all-features -- -D warnings` vert.