v0.3.6-pre.001-fix.001

This commit is contained in:
2026-09-01 10:43:09 +02:00
parent 6f2d0a092a
commit ecfc30a94b
25 changed files with 706 additions and 392 deletions

View File

@@ -1,12 +1,12 @@
# file: Cargo.toml # file: Cargo.toml
# version: 393 # version: 394
[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-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-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.1" version = "0.3.6-pre.1.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,5 +1,5 @@
<!-- file: deltas/0.1.4/pre.004.md --> <!-- file: deltas/0.1.4/pre.004.md -->
<!-- version: 2 --> <!-- version: 3 -->
# Delta 0.1.4-pre.004 — squelette Rust/Tauri de `ksp-app-config-desk` # Delta 0.1.4-pre.004 — squelette Rust/Tauri de `ksp-app-config-desk`
@@ -75,7 +75,7 @@ La bibliothèque utilise les crate types Tauri usuels `staticlib`, `cdylib` et `
Les versions ont été revérifiées au moment de cette tranche : Les versions ont été revérifiées au moment de cette tranche :
| Dépendance | Version auditée | Contrainte workspace | Usage immédiat | | Dépendance | Version auditée | Contrainte workspace | Usage immédiat |
| ------------- | --------------: | -------------------: | -------------------------- | |---------------|----------------:|---------------------:|------------------------|
| `tauri` | `2.11.5` | `^2.11` | runtime/application | | `tauri` | `2.11.5` | `^2.11` | runtime/application |
| `tauri-build` | `2.6.3` | `^2.6` | build script Tauri | | `tauri-build` | `2.6.3` | `^2.6` | build script Tauri |
| `fs2` | `0.4.3` | `^0.4` | verrou single-instance | | `fs2` | `0.4.3` | `^0.4` | verrou single-instance |
@@ -142,7 +142,7 @@ La destination de build est fixée dès maintenant à :
Le premier couple de ports desk est réservé : Le premier couple de ports desk est réservé :
| Usage | Port | | Usage | Port |
| --------- | ---: | |-----------|-----:|
| Vite HTTP | 1430 | | Vite HTTP | 1430 |
| Vite HMR | 1431 | | Vite HMR | 1431 |

View File

@@ -1,5 +1,5 @@
<!-- file: deltas/0.1.4/pre.005-fix.001.md --> <!-- file: deltas/0.1.4/pre.005-fix.001.md -->
<!-- version: 1 --> <!-- version: 2 -->
# `0.1.4-pre.005-fix.001` — Classification npm et commande Tauri workspace # `0.1.4-pre.005-fix.001` — Classification npm et commande Tauri workspace
@@ -98,7 +98,7 @@ Capability: tracing:default
## 7. Fichiers modifiés ## 7. Fichiers modifiés
| Fichier | Action | | Fichier | Action |
| ---------------------------------------------- | ------: | |------------------------------------------------|--------:|
| `Cargo.toml` | modifié | | `Cargo.toml` | modifié |
| `crates/ksp-app-config-desk/package.json` | modifié | | `crates/ksp-app-config-desk/package.json` | modifié |
| `crates/ksp-app-config-desk/README.md` | modifié | | `crates/ksp-app-config-desk/README.md` | modifié |

View File

@@ -1,5 +1,5 @@
<!-- file: deltas/0.1.4/pre.005.md --> <!-- file: deltas/0.1.4/pre.005.md -->
<!-- version: 2 --> <!-- version: 3 -->
# Delta 0.1.4-pre.005 — gabarit frontend Vite/TypeScript/SCSS et tracing Tauri # Delta 0.1.4-pre.005 — gabarit frontend Vite/TypeScript/SCSS et tracing Tauri
@@ -98,7 +98,7 @@ La permission tracing entre dans le même delta que le plugin, conformément à
Les générations actuelles ont été revérifiées avant rédaction du manifest : Les générations actuelles ont été revérifiées avant rédaction du manifest :
| Dépendance | Version actuelle auditée | Contrainte déclarée | | Dépendance | Version actuelle auditée | Contrainte déclarée |
| ---------------------------------- | -----------------------: | ------------------: | |---------------------------------|-------------------------:|--------------------:|
| `@fltsci/tauri-plugin-tracing` | `0.3.4` | `^0.3` | | `@fltsci/tauri-plugin-tracing` | `0.3.4` | `^0.3` |
| `@fortawesome/fontawesome-free` | `7.3.1` | `^7.3` | | `@fortawesome/fontawesome-free` | `7.3.1` | `^7.3` |
| `@tauri-apps/api` | `2.11.1` | `^2.11` | | `@tauri-apps/api` | `2.11.1` | `^2.11` |
@@ -156,7 +156,7 @@ afin de ne pas introduire dès la première application KSP des options désorma
Le serveur est configuré ainsi : Le serveur est configuré ainsi :
| Usage | Port | Politique | | Usage | Port | Politique |
| ------------------------ | ---: | --------- | |-------------------|-----:|-----------|
| Vite HTTP | 1430 | strict | | Vite HTTP | 1430 | strict |
| WebSocket dev/HMR | 1431 | dédié | | WebSocket dev/HMR | 1431 | dédié |

View File

@@ -1,5 +1,5 @@
<!-- file: deltas/0.1.4/pre.006.md --> <!-- file: deltas/0.1.4/pre.006.md -->
<!-- version: 1 --> <!-- version: 2 -->
# `0.1.4-pre.006` — Bootstrap backend, `AppState` et runtime Logging initial # `0.1.4-pre.006` — Bootstrap backend, `AppState` et runtime Logging initial
@@ -194,7 +194,7 @@ ts-rs
## 11. Fichiers ## 11. Fichiers
| Fichier | Action | | Fichier | Action |
| ----------------------------------------------------------- | ------: | |-------------------------------------------------------|--------:|
| `Cargo.toml` | modifié | | `Cargo.toml` | modifié |
| `crates/ksp-app-config-desk/Cargo.toml` | modifié | | `crates/ksp-app-config-desk/Cargo.toml` | modifié |
| `crates/ksp-app-config-desk/src/app_state.rs` | ajouté | | `crates/ksp-app-config-desk/src/app_state.rs` | ajouté |

View File

@@ -1,5 +1,5 @@
<!-- file: deltas/0.1.4/pre.007.md --> <!-- file: deltas/0.1.4/pre.007.md -->
<!-- version: 1 --> <!-- version: 2 -->
# `0.1.4-pre.007` — Bridge frontend logging KSP # `0.1.4-pre.007` — Bridge frontend logging KSP
@@ -166,7 +166,7 @@ Le derive TS-RS ajoute le test d'export de `FrontendLogPayloadDto`.
## 11. Fichiers ## 11. Fichiers
| Fichier | Action | | Fichier | Action |
| ------------------------------------------------------------- | ------: | |-------------------------------------------------------------|--------:|
| `Cargo.toml` | modifié | | `Cargo.toml` | modifié |
| `crates/ksp-app-config-desk/src/constants.rs` | modifié | | `crates/ksp-app-config-desk/src/constants.rs` | modifié |
| `crates/ksp-app-config-desk/src/errors.rs` | modifié | | `crates/ksp-app-config-desk/src/errors.rs` | modifié |

View File

@@ -1,5 +1,5 @@
<!-- file: deltas/0.1.4/pre.008-fix.001.md --> <!-- file: deltas/0.1.4/pre.008-fix.001.md -->
<!-- version: 1 --> <!-- version: 2 -->
# `0.1.4-pre.008-fix.001` — Contextes splash numériques et réexports de labels inutiles # `0.1.4-pre.008-fix.001` — Contextes splash numériques et réexports de labels inutiles
@@ -87,7 +87,7 @@ Il vérifie que les erreurs bornées conservent bien ces valeurs dans `Error::co
## 6. Fichiers modifiés ## 6. Fichiers modifiés
| Fichier | Action | | Fichier | Action |
| ------------------------------------------------------ | ------: | |---------------------------------------------------|--------:|
| `Cargo.toml` | modifié | | `Cargo.toml` | modifié |
| `crates/ksp-app-config-desk/src/lib.rs` | modifié | | `crates/ksp-app-config-desk/src/lib.rs` | modifié |
| `crates/ksp-app-config-desk/src/splash.rs` | modifié | | `crates/ksp-app-config-desk/src/splash.rs` | modifié |

View File

@@ -1,5 +1,5 @@
<!-- file: deltas/0.1.4/pre.008-fix.003.md --> <!-- file: deltas/0.1.4/pre.008-fix.003.md -->
<!-- version: 1 --> <!-- version: 2 -->
# `0.1.4-pre.008-fix.003` — visibilité des logs `debug` de Config Desk # `0.1.4-pre.008-fix.003` — visibilité des logs `debug` de Config Desk
@@ -58,7 +58,7 @@ ksp-app-config-desk -> Debug
## 5. Fichiers modifiés ## 5. Fichiers modifiés
| Fichier | Action | | Fichier | Action |
| ------------------------------------------------- | ------: | |-----------------------------------------------|--------:|
| `Cargo.toml` | modifié | | `Cargo.toml` | modifié |
| `config/std.logging.json` | modifié | | `config/std.logging.json` | modifié |
| `crates/ksp-config-lib/unit_tests/logging.rs` | modifié | | `crates/ksp-config-lib/unit_tests/logging.rs` | modifié |

View File

@@ -0,0 +1,125 @@
<!-- file: deltas/0.3.6/pre.001-fix.001.md -->
<!-- version: 1 -->
# Delta `0.3.6-pre.001-fix.001` — sizing souple et audit Markdown effectif
## Base requise
```text
0.3.6-pre.001
workspace.package.version = 0.3.6-pre.1
```
Ce fix corrige la tranche de cadrage `pre.001`. Il modifie un script d'audit consommé par le gate ; conformément à `VER-ID-007` et `VER-ID-010`, la version Cargo devient `0.3.6-pre.1.fix.1`.
## Objectif
- remplacer le forecast tabulaire par une hiérarchie éditable `### pre.NNN` puis `#### pre.NNN-fix.MMM` ;
- corriger le faux négatif de `scripts/audit_markdown_tables.py` ;
- imposer l'alignement source gauche, droit ou centré indiqué par la ligne séparatrice ;
- réaligner les documents actifs révélés par le validateur corrigé sans réécrire les anciens deltas publiés.
## Cause racine
`_is_separator_row` appliquait la regex aux cellules brutes. Une ligne telle que `| --- | ---: |` contient des espaces dans chaque cellule et n'était donc pas reconnue comme séparateur. Le tableau entier était ignoré, son compteur n'augmentait pas et aucune largeur n'était contrôlée.
Le validateur contrôlait par ailleurs uniquement le padding droit des cellules de contenu. Il n'appliquait pas la sémantique de `---:` pour une colonne alignée à droite ni celle de `:---:` pour une colonne centrée.
## Corrections
### Détection et validation
- détection tolérante par `strip` afin qu'un séparateur plausible mais mal formaté entre dans l'audit ;
- validation canonique stricte du séparateur brut, qui doit remplir la colonne sans espaces ;
- `---` et `:---` : un espace gauche puis padding droit ;
- `---:` : padding gauche puis un espace droit ;
- `:---:` : paddings équilibrés à un espace près ;
- largeur minimale compatible avec trois tirets et les marqueurs d'alignement ;
- erreurs dédiées par orientation.
### Régressions automatisées
Le nouveau test `scripts/tests/test_audit_markdown_tables.py` couvre cinq cas :
- tableau gauche et droit canonique accepté ;
- tableau gauche explicite et centré accepté ;
- séparateur espacé auparavant ignoré désormais rejeté ;
- cellule alignée à gauche sous `---:` rejetée ;
- cellule alignée à droite sous `:---` rejetée.
### Sizing de la v0.3.6
Le tableau du découpage prévisionnel est remplacé par des sous-sections. Chaque prerelease porte son statut, son budget, son entrée, son contenu et sa sortie. `pre.001-fix.001` est inséré directement sous `pre.001`, comme dans le sizing durable du plan 025.
### Réalignement documentaire
Le gate corrigé a révélé 13 documents durables contenant soit un séparateur espacé, soit un padding incompatible avec ses marqueurs. Ils sont réalignés mécaniquement, sans changement sémantique :
```text
docs/formats/KSPWALLET_V1.md
docs/formats/KSPWALLET_V2.md
docs/plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md
docs/plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md
docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md
docs/plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md
docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md
docs/plans/026-V0_3_5_INTERFACE_ACQUISITION_EVENTS_PLAN.md
docs/plans/027-V0_3_6_JOB_API_BACKFILL_PLAN.md
docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md
docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md
docs/validation/022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md
docs/validation/023-V0_3_6_JOB_API_BACKFILL.md
```
Les deltas antérieurs restent inchangés conformément à `DOC-TABLE-006`.
## Fichiers ajoutés
```text
scripts/tests/test_audit_markdown_tables.py
deltas/0.3.6/pre.001-fix.001.md
```
## Fichiers modifiés
```text
Cargo.toml
scripts/audit_markdown_tables.py
docs/rules/RULES_DOCUMENTATION.md
les 13 documents durables listés dans la section de réalignement
```
## Fichiers supprimés
Aucun.
## Décisions prises
- le script d'audit est un artefact de code d'outillage et impose donc le suffixe Cargo `.fix.1` ;
- le séparateur reste détecté de façon tolérante mais validé selon la forme canonique stricte ;
- l'alignement source suit ses marqueurs Markdown, pas seulement le rendu visuel ;
- le réalignement historique est limité aux documents durables encore audités, jamais aux deltas publiés ;
- aucun contenu fonctionnel Job ou Backfill n'est ouvert par ce fix.
## Validations exécutées
```text
python3 -m unittest scripts/tests/test_audit_markdown_tables.py
-> 5 tests PASS
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.6
-> clean, 264 tables / 141 fichiers
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
```
## Validations non exécutées
`cargo` n'est pas installé dans l'environnement d'assemblage. `cargo fmt`, `cargo check`, `cargo clippy` et `cargo test` ne sont pas annoncés comme réussis. Aucun fichier Rust ou manifeste de crate n'est modifié, mais l'opérateur doit rejouer le gate demandé après application du fix.
## Questions ouvertes
Aucune question ne bloque `pre.002`.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/formats/KSPWALLET_V1.md --> <!-- file: docs/formats/KSPWALLET_V1.md -->
<!-- version: 15 --> <!-- version: 16 -->
# `.kspwallet` V1 — spécification du format natif Wallet KSP # `.kspwallet` V1 — spécification du format natif Wallet KSP

View File

@@ -1,5 +1,5 @@
<!-- file: docs/formats/KSPWALLET_V2.md --> <!-- file: docs/formats/KSPWALLET_V2.md -->
<!-- version: 4 --> <!-- version: 5 -->
# `.kspwallet` V2 — spécification du wire binaire natif KSP # `.kspwallet` V2 — spécification du wire binaire natif KSP

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md --> <!-- file: docs/plans/005-V0_1_3_CONFIG_FOUNDATION_PLAN.md -->
<!-- version: 20 --> <!-- version: 21 -->
# Plan `0.1.3` — Configuration foundation # Plan `0.1.3` — Configuration foundation
@@ -1986,4 +1986,3 @@ Le `pre.001-fix.003` est validable lorsque les décisions suivantes sont accept
- les évolutions `ksp-logging-lib` sont explicites en `pre.004` (contrats/settings), `pre.005` (runtime multi-sink + level/target/formats) puis `pre.006` (routing structuré domain), avant gel du schema Logging ; - les évolutions `ksp-logging-lib` sont explicites en `pre.004` (contrats/settings), `pre.005` (runtime multi-sink + level/target/formats) puis `pre.006` (routing structuré domain), avant gel du schema Logging ;
- chaque prerelease vise environ 1520 minutes de travail effectif et doit être scindée si ce budget devient manifestement irréaliste ; - chaque prerelease vise environ 1520 minutes de travail effectif et doit être scindée si ce budget devient manifestement irréaliste ;
- aucune implémentation `pre.002` ne commence avant validation utilisateur de ce plan corrigé. - aucune implémentation `pre.002` ne commence avant validation utilisateur de ce plan corrigé.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md --> <!-- file: docs/plans/006-V0_1_4_CONFIG_DESKTOP_PLAN.md -->
<!-- version: 29 --> <!-- version: 30 -->
# Plan `0.1.4` — `ksp-app-config-desk` # Plan `0.1.4` — `ksp-app-config-desk`
@@ -248,7 +248,7 @@ Les applications suivantes incrémentent le couple de deux ports (`1432/1433`, p
Aucune dépendance n'est ajoutée par `pre.001`. Les versions suivantes ont été revérifiées depuis les registres/documentations officiels afin de fixer la génération candidate à réévaluer **au moment exact de l'ajout** : Aucune dépendance n'est ajoutée par `pre.001`. Les versions suivantes ont été revérifiées depuis les registres/documentations officiels afin de fixer la génération candidate à réévaluer **au moment exact de l'ajout** :
| Dépendance | Version actuelle auditée | Usage envisagé | | Dépendance | Version actuelle auditée | Usage envisagé |
| ------------------------------- | -----------------------: | -------------------------------------------- | |---------------------------------|-------------------------:|----------------------------------------------|
| `tauri` | `2.11.5` | runtime desktop | | `tauri` | `2.11.5` | runtime desktop |
| `tauri-build` | `2.6.3` | build Tauri | | `tauri-build` | `2.6.3` | build Tauri |
| `tauri-plugin-tracing` | `0.3.4` | intégration tracing à la frontière Tauri | | `tauri-plugin-tracing` | `0.3.4` | intégration tracing à la frontière Tauri |
@@ -695,7 +695,7 @@ Le shell applique également une instrumentation frontend systématique : clics
Les noms ci-dessous sont les noms fonctionnels cibles ; ils pourront être normalisés avant implémentation, mais leurs responsabilités sont fixées. Les noms ci-dessous sont les noms fonctionnels cibles ; ils pourront être normalisés avant implémentation, mais leurs responsabilités sont fixées.
| Commande Tauri | Service interne | API KSP principale | Secret réel ? | | Commande Tauri | Service interne | API KSP principale | Secret réel ? |
| ------------------------------ | ------------------------------------ | --------------------------------------------------------------------------- | -------------------------------------------: | |--------------------------------|--------------------------------------|-----------------------------------------------------------------------------|---------------------------------------------:|
| `get_app_snapshot` | `config_service` + `logging_service` | registry/management + runtime state | non | | `get_app_snapshot` | `config_service` + `logging_service` | registry/management + runtime state | non |
| `list_config_documents` | `config_service` | future vue publique du `ConfigFileRegistry` | non | | `list_config_documents` | `config_service` | future vue publique du `ConfigFileRegistry` | non |
| `inspect_config_document` | `config_service` | `load_validated_document` + `read_source` si erreur | non | | `inspect_config_document` | `config_service` | `load_validated_document` + `read_source` si erreur | non |
@@ -895,7 +895,7 @@ La réussite de ce scénario ferme le critère « une erreur de nouvelle configu
La release ne peut pas être clôturée sans preuve des cas suivants : La release ne peut pas être clôturée sans preuve des cas suivants :
| Cas | Action UI | Résultat attendu | | Cas | Action UI | Résultat attendu |
| --- | ----------------------------- | ------------------------------------------------------------------------------ | |-----|-------------------------------|--------------------------------------------------------------------------------|
| L1 | créer un second profil | profil ajouté via types Config et sauvegardable | | L1 | créer un second profil | profil ajouté via types Config et sauvegardable |
| L2 | modifier le profil existant | mutation persistée via `save_logging_document()` | | L2 | modifier le profil existant | mutation persistée via `save_logging_document()` |
| L3 | profil mono-fichier | console optionnelle + exactement un sink fichier valide | | L3 | profil mono-fichier | console optionnelle + exactement un sink fichier valide |

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md --> <!-- file: docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md -->
<!-- version: 7 --> <!-- version: 8 -->
# Plan `0.2.4` — HTTP Blocks + Economics + compliance HTTP finale # Plan `0.2.4` — HTTP Blocks + Economics + compliance HTTP finale
@@ -225,7 +225,7 @@ Les SIMDs `Review` liés au block-revenue sharing, notamment SIMD-0123, peuvent
## Matrice Blocks — 10 wrappers ## Matrice Blocks — 10 wrappers
| Méthode | Requête à couvrir | Résultat à préserver | Contraintes / décisions `KSP-TRANSPORT-007` | | Méthode | Requête à couvrir | Résultat à préserver | Contraintes / décisions `KSP-TRANSPORT-007` |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | |-------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `getBlock` | `slot`; second paramètre absent, bare encoding legacy, ou config `{commitment, encoding, transactionDetails, maxSupportedTransactionVersion, rewards}` | `object ou null`; `previousBlockhash`, `blockhash`, `parentSlot`, transactions/signatures/rewards selon config, `numRewardPartitions`, `blockTime`, `blockHeight` | commitment runtime au moins `confirmed`; réutiliser les encodings/version/transaction wire de `0.2.3`; préserver omission vs null; `numRewardPartitions` suit SIMD-0118; les rewards préservent `commissionBps` de SIMD-0291; garder les erreurs runtime de bloc/version comme erreurs RPC, sans les masquer | | `getBlock` | `slot`; second paramètre absent, bare encoding legacy, ou config `{commitment, encoding, transactionDetails, maxSupportedTransactionVersion, rewards}` | `object ou null`; `previousBlockhash`, `blockhash`, `parentSlot`, transactions/signatures/rewards selon config, `numRewardPartitions`, `blockTime`, `blockHeight` | commitment runtime au moins `confirmed`; réutiliser les encodings/version/transaction wire de `0.2.3`; préserver omission vs null; `numRewardPartitions` suit SIMD-0118; les rewards préservent `commissionBps` de SIMD-0291; garder les erreurs runtime de bloc/version comme erreurs RPC, sans les masquer |
| `getBlockCommitment` | `slot` uniquement | `{commitment: array<u64> ou null, totalStake: u64}` | aucune config à inventer; préserver commitment nullable | | `getBlockCommitment` | `slot` uniquement | `{commitment: array<u64> ou null, totalStake: u64}` | aucune config à inventer; préserver commitment nullable |
| `getBlockHeight` | config contextuelle optionnelle `{commitment, minContextSlot}` | `u64` | réutiliser `SolanaContextConfig`; `minContextSlot` est transmis tel quel au runtime | | `getBlockHeight` | config contextuelle optionnelle `{commitment, minContextSlot}` | `u64` | réutiliser `SolanaContextConfig`; `minContextSlot` est transmis tel quel au runtime |
@@ -270,7 +270,7 @@ Les champs top-level dont la présence dépend de la config (`transactions`, `si
## Matrice Economics — 5 wrappers ## Matrice Economics — 5 wrappers
| Méthode | Requête à couvrir | Résultat à préserver | Contraintes / décisions `KSP-TRANSPORT-007` | | Méthode | Requête à couvrir | Résultat à préserver | Contraintes / décisions `KSP-TRANSPORT-007` |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | |-----------------------------|-----------------------------------------------------------------------------------|--------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `getInflationGovernor` | config commitment optionnelle | `{initial,terminal,taper,foundation,foundationTerm}` en `f64` | réutiliser `SolanaCommitmentConfig`; aucun contexte de réponse | | `getInflationGovernor` | config commitment optionnelle | `{initial,terminal,taper,foundation,foundationTerm}` en `f64` | réutiliser `SolanaCommitmentConfig`; aucun contexte de réponse |
| `getInflationRate` | aucun paramètre | `{total,validator,foundation,epoch}` | requête exacte `params: []` | | `getInflationRate` | aucun paramètre | `{total,validator,foundation,epoch}` | requête exacte `params: []` |
| `getInflationReward` | liste ordonnée d'adresses; config optionnelle `{epoch,commitment,minContextSlot}` | `Vec<Option<Reward>>` positionnel | commitment >= `confirmed`; ordre/cardinalité identiques aux entrées; préserver `commission: u8 ou null` et `commissionBps: u16` optionnel/omis de Agave `v4.2.1` conformément à SIMD-0291; aucune limite fixe d'adresses inventée | | `getInflationReward` | liste ordonnée d'adresses; config optionnelle `{epoch,commitment,minContextSlot}` | `Vec<Option<Reward>>` positionnel | commitment >= `confirmed`; ordre/cardinalité identiques aux entrées; préserver `commission: u8 ou null` et `commissionBps: u16` optionnel/omis de Agave `v4.2.1` conformément à SIMD-0291; aucune limite fixe d'adresses inventée |

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md --> <!-- file: docs/plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md -->
<!-- version: 16 --> <!-- version: 17 -->
# Plan `0.2.5` — Wallet foundation # Plan `0.2.5` — Wallet foundation

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md --> <!-- file: docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md -->
<!-- version: 18 --> <!-- version: 19 -->
# Plan `0.2.7` — WebSocket Solana standard # Plan `0.2.7` — WebSocket Solana standard

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/026-V0_3_5_INTERFACE_ACQUISITION_EVENTS_PLAN.md --> <!-- file: docs/plans/026-V0_3_5_INTERFACE_ACQUISITION_EVENTS_PLAN.md -->
<!-- version: 4 --> <!-- version: 5 -->
# Plan `0.3.5` — Interface passive acquisition events # Plan `0.3.5` — Interface passive acquisition events
@@ -224,7 +224,7 @@ Une égalité de noms ne suffit pas. Une proximité de commitment ne suffit pas.
## 6. Inventaire producer -> nature de fait ## 6. Inventaire producer -> nature de fait
| Producer / surface | Nature du fait | Champs structurants obligatoires | Optionalité utile | Ordre / lifecycle | Timestamp semantics | Error semantics | Metadata session/provider | Volume potentiel | Persistent/replayable ? | | Producer / surface | Nature du fait | Champs structurants obligatoires | Optionalité utile | Ordre / lifecycle | Timestamp semantics | Error semantics | Metadata session/provider | Volume potentiel | Persistent/replayable ? |
| -------------------------------------- | ----------------------------------- | ----------------------------------------------------- | --------------------------------- | ------------------------------------------------- | ----------------------------------------- | -------------------------------------- | -------------------------------------- | --------------------- | --------------------------------------- | |----------------------------------------|-------------------------------------|-------------------------------------------------------|-----------------------------------|---------------------------------------------------|-------------------------------------------|----------------------------------------|----------------------------------------|-----------------------|-----------------------------------------|
| Solana WS `slotSubscribe` | progression de slot | slot, parent, root | aucune | event répété à chaque slot traité | aucun | aucune | subscription id hors DTO métier | minime | non | | Solana WS `slotSubscribe` | progression de slot | slot, parent, root | aucune | event répété à chaque slot traité | aucun | aucune | subscription id hors DTO métier | minime | non |
| Solana WS `rootSubscribe` | progression de root | root slot | aucune | event répété lors du changement de root | aucun | aucune | subscription id | minime | non | | Solana WS `rootSubscribe` | progression de root | root slot | aucune | event répété lors du changement de root | aucun | aucune | subscription id | minime | non |
| Solana WS `slotsUpdatesSubscribe` | lifecycle interne slot | slot, type, timestamp | parent/stats/error selon variante | multi-event par slot ; méthode instable | Unix update timestamp en ms | texte seulement pour `dead` | subscription id | faible à modéré | non | | Solana WS `slotsUpdatesSubscribe` | lifecycle interne slot | slot, type, timestamp | parent/stats/error selon variante | multi-event par slot ; méthode instable | Unix update timestamp en ms | texte seulement pour `dead` | subscription id | faible à modéré | non |
@@ -248,7 +248,7 @@ Une égalité de noms ne suffit pas. Une proximité de commitment ne suffit pas.
### 6.1 Consumers actuels et imminents ### 6.1 Consumers actuels et imminents
| Consumer | Besoin actuel / prévu | Dépendance à Interface event | Décision `pre.001` | | Consumer | Besoin actuel / prévu | Dépendance à Interface event | Décision `pre.001` |
| ----------------------------------------- | --------------------------------------------------------- | ---------------------------- | ------------------------------------------------------------------------- | |-------------------------------------------|-----------------------------------------------------------|------------------------------|---------------------------------------------------------------------------|
| `ksp-program-api` | ProgramInstruction / ProgramAccountMeta | non | préserver la surface Program existante ; aucun re-export acquisition | | `ksp-program-api` | ProgramInstruction / ProgramAccountMeta | non | préserver la surface Program existante ; aucun re-export acquisition |
| `0.3.6` premier backfill RAW | range historique -> Transport -> RAW ingestion -> Store | non | ne pas forcer SlotLifecycle dans le backfill | | `0.3.6` premier backfill RAW | range historique -> Transport -> RAW ingestion -> Store | non | ne pas forcer SlotLifecycle dans le backfill |
| futur worker RAW live | subscriptions/fetch live multi-transport -> RAW ingestion | oui, candidat concret | consumer proche justifiant une projection slot lifecycle provider-neutral | | futur worker RAW live | subscriptions/fetch live multi-transport -> RAW ingestion | oui, candidat concret | consumer proche justifiant une projection slot lifecycle provider-neutral |
@@ -258,7 +258,7 @@ Une égalité de noms ne suffit pas. Une proximité de commitment ne suffit pas.
## 7. Matrice de convergence sémantique ## 7. Matrice de convergence sémantique
| Nature candidate | Sources comparées | Intersection exacte retenue | Différences non représentables sans perte | Projection commune lossless pour le fait ciblé ? | Consumer concret | Owner | Décision | | Nature candidate | Sources comparées | Intersection exacte retenue | Différences non représentables sans perte | Projection commune lossless pour le fait ciblé ? | Consumer concret | Owner | Décision |
| ----------------------------- | --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------ | ----------------------------- | ------------------------------ | ------------------- | |-------------------------------|-----------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|-------------------------------------------------------|-------------------------------|--------------------------------|------------------|
| lifecycle slot | slotSubscribe + slotsUpdates + rootSubscribe + Yellowstone Slot | Processed, FirstShredReceived, Completed, CreatedBank, Dead, OptimisticallyConfirmed, Rooted | Frozen ; parent/timestamps/diagnostics ; noms wire Confirmed/Finalized côté Yellowstone | oui, pour l'occurrence `slot + stage` | futur worker RAW live | Interface | ADMIS | | lifecycle slot | slotSubscribe + slotsUpdates + rootSubscribe + Yellowstone Slot | Processed, FirstShredReceived, Completed, CreatedBank, Dead, OptimisticallyConfirmed, Rooted | Frozen ; parent/timestamps/diagnostics ; noms wire Confirmed/Finalized côté Yellowstone | oui, pour l'occurrence `slot + stage` | futur worker RAW live | Interface | ADMIS |
| transaction execution | logsSubscribe + Yellowstone TransactionStatus + Helius transactionSubscribe | `slot + TransactionSignature + Succeeded/Failed` | metadata/provider/detail modes ; commitment/delivery ; erreur source | oui pour le fait d'exécution observée | futur worker RAW live | Interface | ADMIS `pre.003` | | transaction execution | logsSubscribe + Yellowstone TransactionStatus + Helius transactionSubscribe | `slot + TransactionSignature + Succeeded/Failed` | metadata/provider/detail modes ; commitment/delivery ; erreur source | oui pour le fait d'exécution observée | futur worker RAW live | Interface | ADMIS `pre.003` |
| logs realtime | logsSubscribe + transaction/meta Yellowstone/Helius | logs associés à une transaction | volume/bornes, richesse de source, disponibilité selon détail | non admis dans cette release sans consumer/bornes | hydratation possible | Interface si futur gate | IDÉE DIFFÉRÉE | | logs realtime | logsSubscribe + transaction/meta Yellowstone/Helius | logs associés à une transaction | volume/bornes, richesse de source, disponibilité selon détail | non admis dans cette release sans consumer/bornes | hydratation possible | Interface si futur gate | IDÉE DIFFÉRÉE |
@@ -274,7 +274,7 @@ Une égalité de noms ne suffit pas. Une proximité de commitment ne suffit pas.
### 7.1 Lifecycle de slot — ADMIS sous intersection stricte ### 7.1 Lifecycle de slot — ADMIS sous intersection stricte
| Fait commun | Solana standard | Yellowstone | Stage KSP | Décision Interface | Metadata volontairement non commune | | Fait commun | Solana standard | Yellowstone | Stage KSP | Décision Interface | Metadata volontairement non commune |
| ------------------------ | --------------------------------------- | -------------------- | ------------------------- | ------------------ | ------------------------------------------------------------------------------ | |--------------------------|-----------------------------------------|----------------------|---------------------------|--------------------|--------------------------------------------------------------------------------|
| slot traité | `slotSubscribe` | `Processed` | `Processed` | ADMIS | parent/root courant côté WS ; filters/created_at/parent côté Yellowstone | | slot traité | `slotSubscribe` | `Processed` | `Processed` | ADMIS | parent/root courant côté WS ; filters/created_at/parent côté Yellowstone |
| premier shred reçu | `FirstShredReceived` | `FirstShredReceived` | `FirstShredReceived` | ADMIS | timestamp WS ; created_at/filters côté Yellowstone | | premier shred reçu | `FirstShredReceived` | `FirstShredReceived` | `FirstShredReceived` | ADMIS | timestamp WS ; created_at/filters côté Yellowstone |
| ingestion slot complétée | `Completed` | `Completed` | `Completed` | ADMIS | timestamp WS ; created_at/filters côté Yellowstone | | ingestion slot complétée | `Completed` | `Completed` | `Completed` | ADMIS | timestamp WS ; created_at/filters côté Yellowstone |
@@ -474,7 +474,7 @@ Ces APIs ne deviennent pas un prérequis de `0.3.6` : le premier backfill histor
## 10. Anti-duplication Store ## 10. Anti-duplication Store
| Contrat Store comparé | Chevauchement Interface admis | Pourquoi il n'y a pas de seconde vérité | | Contrat Store comparé | Chevauchement Interface admis | Pourquoi il n'y a pas de seconde vérité |
| ------------------------------ | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------ | |-----------------------------|------------------------------------------------|------------------------------------------------------------------------------------------------------|
| `RawTransaction` | slot + signature possibles via execution event | aucun payload/format/hash/block_time ; l'event ne peut reconstruire ni remplacer une transaction RAW | | `RawTransaction` | slot + signature possibles via execution event | aucun payload/format/hash/block_time ; l'event ne peut reconstruire ni remplacer une transaction RAW |
| `RawTransactionReference` | signature sémantiquement apparentée | la référence Store inclut `RawNetworkId` et possède l'identité durable ; Interface reste contextuel | | `RawTransactionReference` | signature sémantiquement apparentée | la référence Store inclut `RawNetworkId` et possède l'identité durable ; Interface reste contextuel |
| `RawTransactionSignature` | même primitive protocolaire 64 octets | wrapper Store et primitive Interface restent owner-specific ; conversion explicite à la composition | | `RawTransactionSignature` | même primitive protocolaire 64 octets | wrapper Store et primitive Interface restent owner-specific ; conversion explicite à la composition |
@@ -527,7 +527,7 @@ future acquisition composition / RAW live worker
## 12. Threat model ## 12. Threat model
| Risque | Menace | Garde planifiée | | Risque | Menace | Garde planifiée |
| ------------------------------ | -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | |--------------------------------|----------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|
| mega enum | Interface devient catalogue de tous les transports | familles admises séparées et étroites ; aucun `Event` générique | | mega enum | Interface devient catalogue de tous les transports | familles admises séparées et étroites ; aucun `Event` générique |
| Option soup | sémantiques différentes fusionnées par champs optionnels | familles séparées : SlotLifecycle / TransactionExecution ; logs/commitment restent distincts | | Option soup | sémantiques différentes fusionnées par champs optionnels | familles séparées : SlotLifecycle / TransactionExecution ; logs/commitment restent distincts |
| persistence creep | event-only devient second Store | aucun RAW/payload/cursor/retention ; `KSP-NOTIFY-*` reste Store API | | persistence creep | event-only devient second Store | aucun RAW/payload/cursor/retention ; `KSP-NOTIFY-*` reste Store API |

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: 1 --> <!-- version: 2 -->
# Plan v0.3.6 — Job API et premier backfill RAW # Plan v0.3.6 — Job API et premier backfill RAW
@@ -63,7 +63,7 @@ Hors périmètre :
Le tableau décrit des comportements observés ; il ne constitue pas une filiation de code. Le tableau décrit des comportements observés ; il ne constitue pas une filiation de code.
| Fonction historique | Preuve fichier, test ou run | Sémantique réelle | Statut KSP | Owner KSP cible | Risque ou différence actuelle | Préversion cible | | Fonction historique | Preuve fichier, test ou run | Sémantique réelle | Statut KSP | Owner KSP cible | Risque ou différence actuelle | Préversion cible |
| --- | --- | --- | --- | --- | --- | --- | |------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------|------------|----------------------------------------------|----------------------------------------------------------------------------|----------------------|
| Sources latest, before et after | `ks-pipeline/src/backfill.rs`, `collect_before_candidates`, `collect_after_candidates` | Pagination d'adresse, ancre exclusive et fenêtre plus récente proche | REPRENDRE | Backfill avec wrappers Transport | L'ordre after doit être figé et l'ancre non atteinte observable | `pre.005`, `pre.008` | | Sources latest, before et after | `ks-pipeline/src/backfill.rs`, `collect_before_candidates`, `collect_after_candidates` | Pagination d'adresse, ancre exclusive et fenêtre plus récente proche | REPRENDRE | Backfill avec wrappers Transport | L'ordre after doit être figé et l'ancre non atteinte observable | `pre.005`, `pre.008` |
| Signatures explicites | `explicit_candidates_are_deduplicated_in_input_order` | Première occurrence conservée et ordre d'entrée stable | REPRENDRE | Backfill | Validation Base58 et limite absentes du type KSP actuel | `pre.005` | | Signatures explicites | `explicit_candidates_are_deduplicated_in_input_order` | Première occurrence conservée et ordre d'entrée stable | REPRENDRE | Backfill | Validation Base58 et limite absentes du type KSP actuel | `pre.005` |
| Déduplication inter-pages | `nearest_newer_candidates_deduplicate_page_entries` | Un candidat identique n'est admis qu'une fois | REPRENDRE | Backfill | Doit couvrir toutes les directions, pas seulement after | `pre.005` | | Déduplication inter-pages | `nearest_newer_candidates_deduplicate_page_entries` | Un candidat identique n'est admis qu'une fois | REPRENDRE | Backfill | Doit couvrir toutes les directions, pas seulement after | `pre.005` |
@@ -83,7 +83,7 @@ Le tableau décrit des comportements observés ; il ne constitue pas une filiati
## 5. Ownership par couche ## 5. Ownership par couche
| Sujet | Propriétaire | Contrat | | Sujet | Propriétaire | Contrat |
| --- | --- | --- | |---------------------------------------|-----------------------------|-----------------------------------------------------|
| Identité, état et annulation d'un Job | `ksp-job-api` | Types publics runtime-neutral et sans effet de bord | | Identité, état et annulation d'un Job | `ksp-job-api` | Types publics runtime-neutral et sans effet de bord |
| Snapshot concret du backfill | `ksp-job-backfill-lib` | Phase, progression, checkpoint et résultat sûrs | | Snapshot concret du backfill | `ksp-job-backfill-lib` | Phase, progression, checkpoint et résultat sûrs |
| Pagination et hydratation Solana | `ksp-onchain-transport-lib` | Wrappers RPC typés existants | | Pagination et hydratation Solana | `ksp-onchain-transport-lib` | Wrappers RPC typés existants |
@@ -117,7 +117,7 @@ La surface concrète du backfill accepte `BackfillRequest`, `HttpTransportPool`
Audit des formes candidates avant choix : Audit des formes candidates avant choix :
| Forme | Runtime-neutralité API | Backpressure | Multi-listener | Livraison terminale | Resynchronisation | Testabilité | Réutilisation Worker future | | Forme | Runtime-neutralité API | Backpressure | Multi-listener | Livraison terminale | Resynchronisation | Testabilité | Réutilisation Worker future |
| --- | --- | --- | --- | --- | --- | --- | --- | |-----------------------------|--------------------------------------|-----------------------------|---------------------------------|-------------------------------------------|--------------------------------|-------------------------------------|----------------------------------------------|
| Polling snapshot par caller | Forte | Naturellement bornée | Oui | Oui si le caller repolle | Snapshot direct | Simple mais latence artificielle | Possible, coûteux si polling serré | | Polling snapshot par caller | Forte | Naturellement bornée | Oui | Oui si le caller repolle | Snapshot direct | Simple mais latence artificielle | Possible, coûteux si polling serré |
| Callback ou sink | Moyenne | Le producer peut bloquer | Composition manuelle | Fragile sur panic ou abandon | Aucune native | Courses et réentrance difficiles | Rejetée | | Callback ou sink | Moyenne | Le producer peut bloquer | Composition manuelle | Fragile sur panic ou abandon | Aucune native | Courses et réentrance difficiles | Rejetée |
| Watch ou latest-value | Forte avec futur abstrait | O(1), coalescence explicite | Oui | Oui, valeur retenue | Snapshot complet courant | Déterministe avec séquences | Bon motif, contrat Worker distinct plus tard | | Watch ou latest-value | Forte avec futur abstrait | O(1), coalescence explicite | Oui | Oui, valeur retenue | Snapshot complet courant | Déterministe avec séquences | Bon motif, contrat Worker distinct plus tard |
@@ -165,7 +165,7 @@ Le fingerprint de scope couvre réseau, adresse ou digest de liste, direction, a
## 9. Sémantique RPC officielle figée ## 9. Sémantique RPC officielle figée
| Appel | Configuration retenue | Sémantique consommée | | Appel | Configuration retenue | Sémantique consommée |
| --- | --- | --- | |---------------------------|----------------------------------------------------------|--------------------------------------------------------------------------------------|
| `getSignaturesForAddress` | engagement, `before`, `until`, `limit`, `minContextSlot` | Résultats du plus récent au plus ancien ; ancres exclusives | | `getSignaturesForAddress` | engagement, `before`, `until`, `limit`, `minContextSlot` | Résultats du plus récent au plus ancien ; ancres exclusives |
| `getTransaction` | engagement, encodage `base64`, version maximale `0` | Transaction confirmée ou `null`, avec slot, block time, transaction, meta et version | | `getTransaction` | engagement, encodage `base64`, version maximale `0` | Transaction confirmée ou `null`, avec slot, block time, transaction, meta et version |
@@ -274,7 +274,7 @@ Le checkpoint contient `JobId`, fingerprint de scope, index de frontière et cur
Annuler est idempotent et fait passer `Running` vers `Cancelling` dès que le producteur observe le token. Annuler est idempotent et fait passer `Running` vers `Cancelling` dès que le producteur observe le token.
| Situation | Décision | | Situation | Décision |
| --- | --- | |---------------------------------------------------|------------------------------------------------------------------------------------|
| Attente ou page RPC en cours | Le futur Transport est abandonné par sélection coopérative | | Attente ou page RPC en cours | Le futur Transport est abandonné par sélection coopérative |
| Hydratation RPC longue | Le futur est abandonné ; aucune persistance n'est fabriquée | | Hydratation RPC longue | Le futur est abandonné ; aucune persistance n'est fabriquée |
| Candidat pas encore admis | Il ne démarre pas | | Candidat pas encore admis | Il ne démarre pas |
@@ -318,7 +318,7 @@ Logging et sécurité :
## 18. Politique de retries ## 18. Politique de retries
| Opération | Propriétaire du retry | Politique Job | | Opération | Propriétaire du retry | Politique Job |
| --- | --- | --- | |---------------------------|------------------------------------|---------------------------------------------------------------|
| `getSignaturesForAddress` | Transport | Aucun retry supplémentaire | | `getSignaturesForAddress` | Transport | Aucun retry supplémentaire |
| `getTransaction` | Transport | Aucun retry supplémentaire | | `getTransaction` | Transport | Aucun retry supplémentaire |
| Écriture Store | Store ou backend selon son contrat | Aucun retry aveugle | | Écriture Store | Store ou backend selon son contrat | Aucun retry aveugle |
@@ -372,26 +372,101 @@ Canaries externes :
- interdiction de dépendance et de type public ; - interdiction de dépendance et de type public ;
- smoke opt-in Devnet plus PostgreSQL configuré, sans endpoint payant ni secret versionné. - smoke opt-in Devnet plus PostgreSQL configuré, sans endpoint payant ni secret versionné.
## 21. Découpage prévisionnel ## 21. Sizing recalibré — prereleases souples
Chaque tranche vise 15 à 20 minutes et doit produire une preuve atomique. Chaque tranche technique vise environ 15 à 20 minutes de travail effectif lorsque le sujet s'y prête. Cette durée est une cible de granularité, pas une durée maximale de compilation, diagnostic ou preuve live.
| Préversion | Critère d'entrée | Contenu atomique | Critère de sortie | Le forecast reste souple : une tranche peut être scindée, fusionnée ou réordonnée par delta si la réalité technique l'exige, sans fusionner les couloirs de fermeture. Un correctif est inséré sous sa prerelease avec un titre `#### pre.NNN-fix.MMM` afin de conserver une hiérarchie éditable.
| --- | --- | --- | --- |
| `pre.001` | Stable v0.3.5 vérifiée | Audit, décisions, plan et validation | Documents, delta et bump de version uniquement | ### `pre.001` Audit, décisions, plan et validation
| `pre.002` | Plan 027 accepté | Identité, lifecycle et token d'annulation Job API | Unitaires API et audit firewalls |
| `pre.003` | Transitions Job stables | Notifications latest-value génériques | Tests multi-listeners et canary externe API | **Statut : réalisé ; corrigé par `pre.001-fix.001`.**
| `pre.004` | Besoin provenance confirmé | Retour Transport observé pour `getTransaction` | Tests routage, retry et endpoint victorieux |
| `pre.005` | Transport observé stable | Scaffold backfill, requêtes, scopes et découverte | Fixtures latest, before, after et explicite | Budget cible : **15-20 min**. L'entrée exigeait la stable v0.3.5 et les deux archives vérifiées. La tranche a produit l'audit KSP, kbot3 et RPC officiel, les décisions d'ownership, le plan, la validation et le bump `0.3.6-pre.1`, sans crate ni code Rust. La sortie est la surface de travail acceptée pour Job API et Backfill.
| `pre.006` | Candidats déterministes | Conversion RAW v1 et provenance | Golden bytes, hash, Base58 et absent ou null |
| `pre.007` | RAW v1 figé | Persistance Store et idempotence | Insert, already, purge, observation, missing et conflit | #### `pre.001-fix.001` — Sizing éditable et audit Markdown effectif
| `pre.008` | Résultats Store typés | Concurrence, résultats et frontière | Fin désordonnée, bornes et checkpoint |
| `pre.009` | Frontière prouvée | Annulation et snapshots concrets | Courses terminales et listener lent | **Statut : réalisé ; correctif d'outillage et documentaire.**
| `pre.010` | Vertical complet | Hardening, canaries externes et firewalls | Tests adversariaux et preuve live si disponible |
| `pre.011` | Aucun défaut fonctionnel ouvert | Gate technique final et smoke opt-in | Workspace vert et cargo trees audités | Le sizing tabulaire est remplacé par les présentes sous-sections afin que chaque correctif futur reste sous sa prerelease. Le validateur Markdown reconnaît désormais les séparateurs plausibles contenant des espaces erronés, applique l'alignement source gauche, droit ou centré indiqué par les marqueurs et possède des tests de régression. Les tableaux de `pre.001` sont réellement réalignés. Comme le script d'audit est du code d'outillage consommé par le gate, la version Cargo devient `0.3.6-pre.1.fix.1`.
| `pre.012` | Gate technique vert | Réconciliation documentaire finale | Architecture, index, roadmap et contrats alignés |
| `pre.013` | Documentation réconciliée | Gate de publication | Changelog, prompt v0.3.7 et archive minimale | ### `pre.002` — Identité, lifecycle et annulation Job API
| `rel.001` | Gate de publication vert | Publication stable | Version stable et deltas Git séparés |
**Statut : planifié.**
Budget cible : **15-20 min**. Entrée : plan 027 corrigé et gate Markdown fiable. Implémenter uniquement identité, transitions et token d'annulation runtime-neutral. Sortie : unitaires API et firewalls verts, sans notification concrète ni backfill.
### `pre.003` — Notifications latest-value génériques
**Statut : planifié.**
Budget cible : **15-20 min**. Entrée : transitions Job stables. Implémenter séquences, snapshot source et resynchronisation multi-listeners. Sortie : listener lent, terminal retenu et canary externe API verts.
### `pre.004` — Provenance Transport observée
**Statut : planifié.**
Budget cible : **15-20 min**. Entrée : besoin de provenance confirmé par le plan. Ajouter le retour observé de `getTransaction` sans dupliquer le client. Sortie : tests de routage, retry et endpoint réellement victorieux verts.
### `pre.005` — Fondation Backfill et découverte
**Statut : planifié.**
Budget cible : **15-20 min**. Entrée : Transport observé stable. Créer la crate, les requêtes, scopes, validations, candidats et pagination. Sortie : fixtures latest, before, after et explicite, avec déduplication stable.
### `pre.006` — Conversion RAW v1 et provenance
**Statut : planifié.**
Budget cible : **15-20 min**. Entrée : candidats déterministes. Implémenter décodage Base58 minimal, payload canonique et provenance. Sortie : golden bytes, hash, absent contre `null` et block time hostile couverts.
### `pre.007` — Persistance Store et idempotence
**Statut : planifié.**
Budget cible : **15-20 min**. Entrée : RAW v1 figé. Composer l'écriture atomique Store normale et les outcomes distincts. Sortie : insert, already present, purge, observation, missing, conflit et relance idempotente couverts.
### `pre.008` — Concurrence, frontier et checkpoint
**Statut : planifié.**
Budget cible : **15-20 min**. Entrée : résultats Store typés. Ajouter admissions bornées, réconciliation hors ordre et reprise. Sortie : frontière contiguë, trous, bornes et checkpoints des quatre scopes prouvés.
### `pre.009` — Annulation et snapshots concrets
**Statut : planifié.**
Budget cible : **15-20 min**. Entrée : frontière prouvée. Intégrer annulation sur les phases critiques et progression Backfill latest-value. Sortie : courses terminales, drainage Store et listener lent couverts.
### `pre.010` — Hardening et canaries externes
**Statut : planifié.**
Budget cible : **15-20 min**. Entrée : vertical déterministe complet. Fermer scénarios adversariaux, API externe, dépendances et sécurité ; exécuter la preuve live si justifiée et disponible. Sortie : aucun défaut fonctionnel ou firewall ouvert.
### `pre.011` — Gate technique final
**Statut : planifié.**
Budget cible : **15-20 min**. Entrée : hardening vert. Rejouer le workspace complet, Clippy, tests et cargo trees, plus le smoke opt-in retenu. Sortie : preuve technique finale consignée sans réconciliation documentaire.
### `pre.012` — Réconciliation documentaire finale
**Statut : planifié.**
Budget cible : **10-15 min**. Entrée : gate technique final vert. Aligner architecture, index, README, USAGE, plan et validation sur la surface prouvée. Sortie : documentation durable cohérente, sans CHANGELOG, ROADMAP ni prompt suivant.
### `pre.013` — Préparation de publication minimale
**Statut : planifié.**
Budget cible : **10-15 min**. Entrée : réconciliation documentaire validée. Modifier uniquement la mécanique Cargo/delta, `CHANGELOG.md`, `ROADMAP.md` et le prompt v0.3.7. Sortie : archive minimale prête pour le gate de publication.
### `rel.001` — Stabilisation et tag `v0.3.6`
**Statut : planifié.**
Entrée : gate de publication vert. Synchroniser la version stable, livrer le delta `rel.001`, effectuer les opérations Git séparées et poser le tag stable. Aucun rattrapage fonctionnel ou documentaire n'est admis.
Le smoke live reste conditionnel à un PostgreSQL explicitement configuré. Son absence n'annule pas la preuve déterministe et ne doit pas conduire à inventer un résultat. Le smoke live reste conditionnel à un PostgreSQL explicitement configuré. Son absence n'annule pas la preuve déterministe et ne doit pas conduire à inventer un résultat.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/rules/RULES_DOCUMENTATION.md --> <!-- file: docs/rules/RULES_DOCUMENTATION.md -->
<!-- version: 6 --> <!-- version: 7 -->
# Règles de documentation # Règles de documentation
@@ -36,9 +36,9 @@ Les règles `DOC-*` s'appliquent aux documents Markdown internes et à leur orga
- **DOC-TABLE-001** — Un tableau Markdown KSP utilise `|` uniquement comme séparateur structurel de colonnes. Un caractère `|` littéral, y compris sous forme échappée `\|`, est interdit dans le contenu dune cellule ; reformuler le contenu, utiliser `/`, `et`, une liste ou un bloc de code hors tableau. - **DOC-TABLE-001** — Un tableau Markdown KSP utilise `|` uniquement comme séparateur structurel de colonnes. Un caractère `|` littéral, y compris sous forme échappée `\|`, est interdit dans le contenu dune cellule ; reformuler le contenu, utiliser `/`, `et`, une liste ou un bloc de code hors tableau.
- **DOC-TABLE-002** — Toutes les lignes dun même tableau ont leurs séparateurs verticaux aux mêmes positions. La largeur de chaque colonne est déterminée par le contenu le plus large de cette colonne, en comptant len-tête et les lignes de données. - **DOC-TABLE-002** — Toutes les lignes dun même tableau ont leurs séparateurs verticaux aux mêmes positions. La largeur de chaque colonne est déterminée par le contenu le plus large de cette colonne, en comptant len-tête et les lignes de données.
- **DOC-TABLE-003** — Chaque cellule de contenu commence par exactement un espace après le séparateur `|` gauche. Dans la cellule qui porte le contenu le plus large dune colonne, il existe aussi exactement un espace entre le contenu et le séparateur `|` droit. Les cellules plus courtes conservent lunique espace gauche et reçoivent uniquement le padding droit nécessaire pour aligner les séparateurs verticaux. - **DOC-TABLE-003** — Lalignement source des cellules suit la ligne séparatrice. Une colonne `|---|` ou `|:---|` est alignée à gauche : chaque contenu possède exactement un espace gauche et uniquement le padding droit nécessaire. Une colonne `|---:|` est alignée à droite : chaque contenu possède exactement un espace droit et uniquement le padding gauche nécessaire. Une colonne `|:---:|` est centrée : les paddings gauche et droit diffèrent dau plus un espace. Chaque cellule conserve au minimum un espace de chaque côté du contenu.
- **DOC-TABLE-004** — La ligne séparatrice en tirets occupe exactement la même largeur que chaque colonne ; les marqueurs `:` de lalignement Markdown restent autorisés lorsquils sont intentionnels. Le résultat attendu est équivalent au reformatage de tableau produit par RustRover, mais la règle structurelle KSP prime sur léditeur utilisé. - **DOC-TABLE-004** — La cellule séparatrice en tirets occupe exactement toute la largeur de la colonne, sans espace entre ses marqueurs et les séparateurs `|`. Elle contient au moins trois tirets ; `:---` sélectionne lalignement gauche explicite, `---:` lalignement droit et `:---:` le centrage. Le résultat attendu est équivalent au reformatage de tableau produit par RustRover, mais la règle structurelle KSP prime sur léditeur utilisé.
- **DOC-TABLE-005** — Lorsquune modification touche une ligne dun tableau, le tableau entier est réaligné avant livraison. `python3 scripts/audit_markdown_tables.py <fichiers-markdown-modifiés>` est le canari mécanique recommandé pour les fichiers concernés ; les blocs de code fenced ne sont pas interprétés comme des tableaux. - **DOC-TABLE-005** — Lorsquune modification touche une ligne dun tableau, le tableau entier est réaligné avant livraison. `python3 scripts/audit_markdown_tables.py <fichiers-markdown-modifiés>` est le canari mécanique recommandé pour les fichiers concernés ; il doit reconnaître et rejeter une ligne séparatrice Markdown plausible même lorsque des espaces erronés lempêchent de respecter `DOC-TABLE-004`. Les blocs de code fenced ne sont pas interprétés comme des tableaux.
- **DOC-TABLE-006** — Limmuabilité des deltas déjà publiés prime sur un reformatage rétrospectif : un ancien fichier `deltas/` nest jamais réécrit uniquement pour satisfaire une règle de présentation introduite ultérieurement. Tout nouveau delta et tout autre tableau modifiable créé ou touché doivent en revanche respecter immédiatement `DOC-TABLE-001` à `DOC-TABLE-005`. - **DOC-TABLE-006** — Limmuabilité des deltas déjà publiés prime sur un reformatage rétrospectif : un ancien fichier `deltas/` nest jamais réécrit uniquement pour satisfaire une règle de présentation introduite ultérieurement. Tout nouveau delta et tout autre tableau modifiable créé ou touché doivent en revanche respecter immédiatement `DOC-TABLE-001` à `DOC-TABLE-005`.
## Espacement vertical Markdown ## Espacement vertical Markdown

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md --> <!-- file: docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md -->
<!-- version: 18 --> <!-- version: 19 -->
# Validation `0.2.7` — WebSocket Solana standard # Validation `0.2.7` — WebSocket Solana standard

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md --> <!-- file: docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md -->
<!-- version: 26 --> <!-- version: 27 -->
# Validation `0.2.8` — Helius LaserStream WebSocket # Validation `0.2.8` — Helius LaserStream WebSocket

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md --> <!-- file: docs/validation/022-V0_3_5_INTERFACE_ACQUISITION_EVENTS.md -->
<!-- version: 9 --> <!-- version: 10 -->
# Validation `0.3.5` — Interface passive acquisition events # Validation `0.3.5` — Interface passive acquisition events
@@ -29,7 +29,7 @@ Cette preuve est l'entrée de `0.3.5`. Elle n'est pas réétiquetée comme valid
## 3. Gate de lecture `pre.001` ## 3. Gate de lecture `pre.001`
| Contrôle | Résultat | Preuve / décision | | Contrôle | Résultat | Preuve / décision |
| ------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------- | |---------------------------------------|----------|-------------------------------------------------------------------------------------------------------|
| règles globales relues | PASS | familles KSP-API/TRANSPORT/STORE/NOTIFY/PROC/REL et DEP applicables relues | | règles globales relues | PASS | familles KSP-API/TRANSPORT/STORE/NOTIFY/PROC/REL et DEP applicables relues |
| architecture durable relue | PASS | Interface passif, Transport protocol/runtime, Store persistant, composition owner des conversions | | architecture durable relue | PASS | Interface passif, Transport protocol/runtime, Store persistant, composition owner des conversions |
| fondation Interface stable relue | PASS | surface Program petite ; dépendance normale Core-only | | fondation Interface stable relue | PASS | surface Program petite ; dépendance normale Core-only |
@@ -46,7 +46,7 @@ Cette preuve est l'entrée de `0.3.5`. Elle n'est pas réétiquetée comme valid
## 4. Matrice de décision par famille ## 4. Matrice de décision par famille
| Famille | Décision | Owner | Motif déterminant | | Famille | Décision | Owner | Motif déterminant |
| ------------------------------------- | ------------------- | ------------------------------ | ---------------------------------------------------------------------------------------- | |---------------------------------------|------------------|--------------------------------|------------------------------------------------------------------------------------------|
| slot lifecycle intersection | ADMIS | Interface | 7 faits compacts normalisés ; détails protocol/provider restent Transport | | slot lifecycle intersection | ADMIS | Interface | 7 faits compacts normalisés ; détails protocol/provider restent Transport |
| transaction execution | ADMIS `pre.003` | Interface | `slot + TransactionSignature + Succeeded/Failed` multi-producer | | transaction execution | ADMIS `pre.003` | Interface | `slot + TransactionSignature + Succeeded/Failed` multi-producer |
| logs realtime | IDÉE DIFFÉRÉE | Interface si futur gate | payload variable/bornes/consumer non démontrés ; ne pas mélanger avec execution | | logs realtime | IDÉE DIFFÉRÉE | Interface si futur gate | payload variable/bornes/consumer non démontrés ; ne pas mélanger avec execution |
@@ -62,7 +62,7 @@ Cette preuve est l'entrée de `0.3.5`. Elle n'est pas réétiquetée comme valid
## 5. Intersection lifecycle retenue ## 5. Intersection lifecycle retenue
| Stage Interface prévu | Producer Solana standard | Producer Yellowstone | Verdict | Détails exclus du contrat commun | | Stage Interface prévu | Producer Solana standard | Producer Yellowstone | Verdict | Détails exclus du contrat commun |
| ------------------------- | -------------------------------------- | -------------------- | ------- | -------------------------------------------------------------------------------- | |---------------------------|----------------------------------------|----------------------|---------|----------------------------------------------------------------------------------|
| `Processed` | `slotSubscribe` | `Processed` | PASS | WS parent/root ; Yellowstone filters/created_at/parent | | `Processed` | `slotSubscribe` | `Processed` | PASS | WS parent/root ; Yellowstone filters/created_at/parent |
| `FirstShredReceived` | `slotsUpdates::FirstShredReceived` | `FirstShredReceived` | PASS | timestamps/metadata source | | `FirstShredReceived` | `slotsUpdates::FirstShredReceived` | `FirstShredReceived` | PASS | timestamps/metadata source |
| `Completed` | `slotsUpdates::Completed` | `Completed` | PASS | timestamps/metadata source | | `Completed` | `slotsUpdates::Completed` | `Completed` | PASS | timestamps/metadata source |
@@ -112,7 +112,7 @@ TransactionExecutionEvent { slot, signature, outcome }
## 7. Validation anti-duplication Store ## 7. Validation anti-duplication Store
| Modèle Store stable | Action `0.3.5` | Justification | | Modèle Store stable | Action `0.3.5` | Justification |
| ------------------------------- | ------------------- | ---------------------------------------------- | |---------------------------------|---------------------|------------------------------------------------|
| `RawTransaction` | inchangé | payload durable/replayable | | `RawTransaction` | inchangé | payload durable/replayable |
| `RawTransactionObservation` | inchangé | provenance persistante | | `RawTransactionObservation` | inchangé | provenance persistante |
| `RawAccountState` | inchangé | état account durable | | `RawAccountState` | inchangé | état account durable |
@@ -162,7 +162,7 @@ Yellowstone gRPC -------------+
## 10. Threat gates ## 10. Threat gates
| Gate | Attendu `0.3.5` | Statut courant | | Gate | Attendu `0.3.5` | Statut courant |
| ------------------------------------ | ------------------------------------------------- | ------------------ | |--------------------------------------|---------------------------------------------------|--------------------|
| mega enum | absent | PLAN PASS | | mega enum | absent | PLAN PASS |
| protocol/provider enum leakage | absent | PLAN PASS | | protocol/provider enum leakage | absent | PLAN PASS |
| timestamp semantics conflated | absent | PLAN PASS | | timestamp semantics conflated | absent | PLAN PASS |
@@ -441,7 +441,7 @@ Contraintes :
### 21.2 Convergence producer ### 21.2 Convergence producer
| Producer | Slot | Signature | Outcome | Metadata volontairement exclue | Verdict | | Producer | Slot | Signature | Outcome | Metadata volontairement exclue | Verdict |
| -------------------------------------- | ----------------------- | ----------------------------------- | ----------------------------------- | -------------------------------------------------------------- | ------- | |---------------------------------|-----------------------|------------------------------------|----------------------------------|--------------------------------------------------------------|---------|
| Solana WS `logsSubscribe` | `context.slot` | base58, décodée par la composition | `err == null` / `err != null` | logs, commitment, subscription | PASS | | Solana WS `logsSubscribe` | `context.slot` | base58, décodée par la composition | `err == null` / `err != null` | logs, commitment, subscription | PASS |
| Yellowstone `TransactionStatus` | `slot` | 64 bytes | `err None` / `err Some` | filters, created_at, is_vote, index, opaque error bytes | PASS | | Yellowstone `TransactionStatus` | `slot` | 64 bytes | `err None` / `err Some` | filters, created_at, is_vote, index, opaque error bytes | PASS |
| Helius `transactionSubscribe` | `slot` si forme typée | signature si forme typée | seulement si erreur déterminable | detail mode, transactionIndex, memo, blockTime, confirmation | PASS* | | Helius `transactionSubscribe` | `slot` si forme typée | signature si forme typée | seulement si erreur déterminable | detail mode, transactionIndex, memo, blockTime, confirmation | PASS* |
@@ -933,4 +933,3 @@ deltas/0.3.5/pre.007.md
``` ```
Aucun autre fichier ne doit être modifié. Aucun autre fichier ne doit être modifié.

View File

@@ -1,9 +1,9 @@
<!-- file: docs/validation/023-V0_3_6_JOB_API_BACKFILL.md --> <!-- file: docs/validation/023-V0_3_6_JOB_API_BACKFILL.md -->
<!-- version: 1 --> <!-- version: 2 -->
# Validation v0.3.6 — Job API et premier backfill RAW # Validation v0.3.6 — Job API et premier backfill RAW
## 1. Statut de `pre.001` ## 1. Statut de `pre.001` et de son fix
- [X] Archive v0.3.5 testée intégralement avant extraction. - [X] Archive v0.3.5 testée intégralement avant extraction.
- [X] Archive kbot3 testée intégralement et isolée de l'arbre source KSP. - [X] Archive kbot3 testée intégralement et isolée de l'arbre source KSP.
@@ -17,11 +17,20 @@
- [X] Plan découpé en tranches atomiques de 15 à 20 minutes. - [X] Plan découpé en tranches atomiques de 15 à 20 minutes.
- [X] Aucun code de crate, manifeste de crate ou test Rust généré en `pre.001`. - [X] Aucun code de crate, manifeste de crate ou test Rust généré en `pre.001`.
- [X] Version workspace ouverte en `0.3.6-pre.1`. - [X] Version workspace ouverte en `0.3.6-pre.1`.
- [X] Sizing converti en sous-sections `### pre.NNN` et `#### pre.NNN-fix.MMM`.
- [X] Faux négatif du validateur Markdown reproduit avec une ligne séparatrice espacée.
- [X] Reconnaissance des séparateurs plausibles corrigée avant validation d'alignement.
- [X] Alignements gauche, droit et centré reliés aux marqueurs de la ligne séparatrice.
- [X] Cinq tests de régression positifs et négatifs ajoutés au validateur.
- [X] Treize documents durables révélés par le validateur corrigé réalignés mécaniquement.
- [X] Audit général corrigé : 264 tables et 141 fichiers propres.
- [X] Anciens deltas publiés laissés byte-inchangés.
- [X] Version workspace du correctif d'outillage synchronisée en `0.3.6-pre.1.fix.1`.
## 2. Preuve des archives d'entrée ## 2. Preuve des archives d'entrée
| Archive | SHA-256 | Résultat ZIP | Usage | | Archive | SHA-256 | Résultat ZIP | Usage |
| --- | --- | --- | --- | |--------------------------------------------------------|--------------------------------------------------------------------|-------------------------------------|--------------------------------|
| `khadhroony-solana-project-v0.3.5-thelatest1.zip` | `c395efb6a09c786069aa5063a7a414b55f8ae24e2b9d6eaa414b2f312cd62588` | 1 515 entrées, test intégral propre | Source exclusive de code | | `khadhroony-solana-project-v0.3.5-thelatest1.zip` | `c395efb6a09c786069aa5063a7a414b55f8ae24e2b9d6eaa414b2f312cd62588` | 1 515 entrées, test intégral propre | Source exclusive de code |
| `khadhroony-bot3_v0.5.3-pre.005-fix010-thelatest1.zip` | `ee47643b9f8b582ee8db97b2381ec107e45aef8c009fee44757531514615d318` | 2 501 entrées, test intégral propre | Référence fonctionnelle isolée | | `khadhroony-bot3_v0.5.3-pre.005-fix010-thelatest1.zip` | `ee47643b9f8b582ee8db97b2381ec107e45aef8c009fee44757531514615d318` | 2 501 entrées, test intégral propre | Référence fonctionnelle isolée |
| `Texte collé.txt` | `0b86c7107349bcbf0a80319ba8cf9aabdd2809f27af9459592667f3e425e8d58` | Sans objet | Journal opérateur v0.3.5 | | `Texte collé.txt` | `0b86c7107349bcbf0a80319ba8cf9aabdd2809f27af9459592667f3e425e8d58` | Sans objet | Journal opérateur v0.3.5 |
@@ -31,9 +40,9 @@ Aucune entrée absolue, traversée, avec séparateur inversé ou lien symbolique
## 3. Baseline v0.3.5 observée ## 3. Baseline v0.3.5 observée
- [X] `scripts/audit_rust_workspace_rules.py` : propre avant modification. - [X] `scripts/audit_rust_workspace_rules.py` : propre avant modification.
- [X] `scripts/audit_markdown_tables.py` : 240 tables et 150 fichiers propres avant modification. - [X] Le résultat historique `240 tables / 150 fichiers` est identifié comme incomplet : les séparateurs espacés n'étaient pas reconnus.
- [X] Audits Rust workspace post-modification : propres, aucune crate Rust ajoutée. - [X] Audits Rust workspace post-modification : propres, aucune crate Rust ajoutée.
- [X] Audit Markdown post-modification complet hors deltas historiques antérieurs : 240 tables et 153 fichiers propres. - [X] Le résultat historique `240 tables / 153 fichiers` de `pre.001` est identifié comme faux positif pour les nouveaux tableaux non alignés.
- [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] 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.

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# file: scripts/audit_markdown_tables.py # file: scripts/audit_markdown_tables.py
# version: 2 # version: 3
"""Validate KSP Markdown tables and vertical spacing for explicitly supplied files or directories.""" """Validate KSP Markdown tables and vertical spacing for explicitly supplied files or directories."""
@@ -46,7 +46,28 @@ def _is_separator_row(line: str) -> bool:
if not _is_table_row(line): if not _is_table_row(line):
return False return False
cells = _cells(line) cells = _cells(line)
return bool(cells) and all(_SEPARATOR_CELL.fullmatch(cell) is not None for cell in cells) return bool(cells) and all(_separator_marker(cell) is not None for cell in cells)
def _separator_marker(cell: str) -> str | None:
marker = cell.strip()
if _SEPARATOR_CELL.fullmatch(marker) is None:
return None
return marker
def _separator_alignment(marker: str) -> str:
if marker.startswith(":") and marker.endswith(":"):
return "center"
if marker.endswith(":"):
return "right"
return "left"
def _space_padding(cell: str) -> tuple[int, int]:
left = len(cell) - len(cell.lstrip(" "))
right = len(cell) - len(cell.rstrip(" "))
return left, right
def _validate_table(path: pathlib.Path, start_line: int, rows: list[str]) -> list[str]: def _validate_table(path: pathlib.Path, start_line: int, rows: list[str]) -> list[str]:
@@ -75,27 +96,46 @@ def _validate_table(path: pathlib.Path, start_line: int, rows: list[str]) -> lis
) )
continue continue
content_cells = [cell for cell in raw_cells if _SEPARATOR_CELL.fullmatch(cell) is None] content_cells = [cell for row_index, cell in enumerate(raw_cells) if row_index != 1]
if not content_cells: if not content_cells:
errors.append(f"{path}:{start_line}: column {column_index + 1} has no header/data content") errors.append(f"{path}:{start_line}: column {column_index + 1} has no header/data content")
continue continue
max_content_width = max(len(cell.strip()) for cell in content_cells) max_content_width = max(len(cell.strip()) for cell in content_cells)
required_width = max_content_width + 2 marker = _separator_marker(raw_cells[1])
if marker is None:
errors.append(f"{path}:{start_line + 1}: separator for column {column_index + 1} is malformed")
continue
minimum_separator_width = 3 + marker.count(":")
required_width = max(max_content_width + 2, minimum_separator_width)
if expected_width != required_width: if expected_width != required_width:
errors.append( errors.append(
f"{path}:{start_line}: column {column_index + 1} width is {expected_width}; expected {required_width} " f"{path}:{start_line}: column {column_index + 1} width is {expected_width}; expected {required_width} "
"(longest content plus exactly one space on each side)" "(longest content plus outer padding, or the minimum Markdown separator width)"
) )
alignment = _separator_alignment(marker)
for cell in content_cells: for cell in content_cells:
if len(cell) < 2 or not cell.startswith(" ") or cell.startswith(" ") or not cell.endswith(" "): content_width = len(cell.strip())
left_padding, right_padding = _space_padding(cell)
if content_width + left_padding + right_padding != len(cell) or left_padding < 1 or right_padding < 1:
errors.append( errors.append(
f"{path}:{start_line}: column {column_index + 1} content cells must start with exactly one space and use right padding only" f"{path}:{start_line}: column {column_index + 1} content cells must use spaces only for outer alignment padding"
) )
break break
if len(cell.strip()) == max_content_width and cell.endswith(" "): expected_padding = expected_width - content_width
if alignment == "left" and (left_padding != 1 or right_padding != expected_padding - 1):
errors.append( errors.append(
f"{path}:{start_line}: column {column_index + 1} widest content must have exactly one space before the closing pipe" f"{path}:{start_line}: column {column_index + 1} is left-aligned; content must use one leading space and right padding only"
)
break
if alignment == "right" and (right_padding != 1 or left_padding != expected_padding - 1):
errors.append(
f"{path}:{start_line}: column {column_index + 1} is right-aligned; content must use left padding and one trailing space"
)
break
if alignment == "center" and abs(left_padding - right_padding) > 1:
errors.append(
f"{path}:{start_line}: column {column_index + 1} is centered; left and right padding may differ by at most one space"
) )
break break

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env python3
# file: scripts/tests/test_audit_markdown_tables.py
# version: 1
"""Regression tests for the KSP Markdown table audit."""
from __future__ import annotations
import pathlib
import sys
import tempfile
import unittest
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1]))
import audit_markdown_tables
class MarkdownTableAuditTests(unittest.TestCase):
"""Cover table recognition and source alignment semantics."""
def audit(self, contents: str) -> tuple[int, list[str]]:
"""Audit one temporary Markdown fixture."""
with tempfile.TemporaryDirectory() as directory:
path = pathlib.Path(directory) / "fixture.md"
path.write_text(contents, encoding="utf-8")
return audit_markdown_tables._audit_file(path)
def test_accepts_left_and_right_aligned_columns(self) -> None:
"""Canonical left and right padding follows the separator markers."""
table_count, errors = self.audit("| Name | Count |\n|------|------:|\n| A | 2 |\n")
self.assertEqual(table_count, 1)
self.assertEqual(errors, [])
def test_accepts_explicit_left_and_centered_columns(self) -> None:
"""Leading and paired colons select left and centered alignment."""
table_count, errors = self.audit("| Name | State |\n|:-----|:-----:|\n| A | ok |\n")
self.assertEqual(table_count, 1)
self.assertEqual(errors, [])
def test_rejects_spaced_separator_that_was_previously_skipped(self) -> None:
"""A malformed but recognizable separator is audited instead of ignored."""
table_count, errors = self.audit("| Name | Count |\n| --- | ---: |\n| A | 2 |\n")
self.assertEqual(table_count, 1)
self.assertTrue(errors)
def test_rejects_left_padding_in_right_aligned_column(self) -> None:
"""A trailing colon requires right-aligned source cells."""
table_count, errors = self.audit("| Name | Count |\n|------|------:|\n| A | 2 |\n")
self.assertEqual(table_count, 1)
self.assertTrue(any("right-aligned" in error for error in errors))
def test_rejects_right_padding_in_explicit_left_column(self) -> None:
"""A leading colon requires left-aligned source cells."""
table_count, errors = self.audit("| Name | Count |\n|:-----|-------|\n| A | 2 |\n")
self.assertEqual(table_count, 1)
self.assertTrue(any("left-aligned" in error for error in errors))
if __name__ == "__main__":
unittest.main()