v0.2.14-pre.003
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
# file: Cargo.toml
|
# file: Cargo.toml
|
||||||
# version: 314
|
# version: 315
|
||||||
|
|
||||||
[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-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-wallet-lib"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.2.14-pre.2"
|
version = "0.2.14-pre.3"
|
||||||
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"
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<!-- file: crates/ksp-program-api/README.md -->
|
<!-- file: crates/ksp-program-api/README.md -->
|
||||||
<!-- version: 1 -->
|
<!-- version: 2 -->
|
||||||
|
|
||||||
# ksp-program-api
|
# ksp-program-api
|
||||||
|
|
||||||
`ksp-program-api` est la façade publique ouverte du domaine Program KSP. Elle est destinée aux implémentations officielles futures comme aux crates Program externes et ne possède pas les implémentations concrètes.
|
`ksp-program-api` est la façade publique ouverte du domaine Program KSP. Elle est destinée aux implémentations officielles futures comme aux crates Program externes et ne possède pas les implémentations concrètes.
|
||||||
|
|
||||||
La tranche initiale `0.2.14-pre.002` matérialise uniquement le scaffold et les types déjà possédés par les couches fondatrices. Aucun trait decoder n'est encore publié.
|
À partir de `0.2.14-pre.003`, la foundation expose les types Core/Interface retenus ainsi que le vocabulaire minimal de reconnaissance et d'outcome de décodage. Le trait decoder reste réservé à la tranche suivante.
|
||||||
|
|
||||||
## Ownership
|
## Ownership
|
||||||
|
|
||||||
@@ -35,11 +35,43 @@ ProgramAccountMeta
|
|||||||
ProgramInstruction
|
ProgramInstruction
|
||||||
```
|
```
|
||||||
|
|
||||||
`ksp-program-api` les réexporte depuis son crate-root pour offrir une façade de consommation stable sans dupliquer leurs types ni transférer leur ownership.
|
Program API possède désormais :
|
||||||
|
|
||||||
## Surface de scaffold
|
```text
|
||||||
|
ProgramInstructionRecognition
|
||||||
|
ProgramInstructionDecodeOutcome<Decoded>
|
||||||
|
```
|
||||||
|
|
||||||
La façade `pre.002` expose exactement :
|
`ksp-program-api` réexporte l'ensemble depuis son crate-root pour offrir une façade de consommation stable sans dupliquer les types Core/Interface ni transférer leur ownership.
|
||||||
|
|
||||||
|
## Recognition
|
||||||
|
|
||||||
|
`ProgramInstructionRecognition` est `#[non_exhaustive]` et possède trois états :
|
||||||
|
|
||||||
|
```text
|
||||||
|
NoMatch l'implémentation ne revendique pas l'instruction
|
||||||
|
ProgramMatch le Program ou la famille correspond, sans reconnaissance exacte
|
||||||
|
ExactMatch l'implémentation affirme un match instruction-local exact
|
||||||
|
```
|
||||||
|
|
||||||
|
Cette reconnaissance ne contient aucun score, priorité, proof, confidence, discriminator textuel ou inventaire central de Programs.
|
||||||
|
|
||||||
|
## Decode outcome
|
||||||
|
|
||||||
|
`ProgramInstructionDecodeOutcome<Decoded>` est également `#[non_exhaustive]` :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Decoded(Decoded) valeur typée possédée par l'implémentation
|
||||||
|
Unsupported instruction connue mais non supportée par cette capability
|
||||||
|
```
|
||||||
|
|
||||||
|
Un futur `decode(...)` utilisera le `Result` Core : une erreur de validation/décodage restera donc `Err`, sans variante parallèle `Failed`.
|
||||||
|
|
||||||
|
Le `Debug` de l'outcome n'impose pas `Decoded: Debug` et n'affiche jamais la valeur `Decoded`. Il produit uniquement le nom sûr de l'état (`Decoded` ou `Unsupported`).
|
||||||
|
|
||||||
|
## Surface actuelle
|
||||||
|
|
||||||
|
La façade `pre.003` expose :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Error
|
Error
|
||||||
@@ -49,16 +81,16 @@ Result
|
|||||||
Pubkey
|
Pubkey
|
||||||
ProgramAccountMeta
|
ProgramAccountMeta
|
||||||
ProgramInstruction
|
ProgramInstruction
|
||||||
|
ProgramInstructionRecognition
|
||||||
|
ProgramInstructionDecodeOutcome<Decoded>
|
||||||
```
|
```
|
||||||
|
|
||||||
Aucun module interne n'est public.
|
Aucun module interne n'est public.
|
||||||
|
|
||||||
Les contrats suivants restent réservés aux tranches suivantes :
|
Le contrat suivant reste réservé à `pre.004` :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
ProgramInstructionRecognition pre.003
|
ProgramInstructionDecoder
|
||||||
ProgramInstructionDecodeOutcome<T> pre.003
|
|
||||||
ProgramInstructionDecoder pre.004
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Frontières
|
## Frontières
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!-- file: crates/ksp-program-api/USAGE.md -->
|
<!-- file: crates/ksp-program-api/USAGE.md -->
|
||||||
<!-- version: 1 -->
|
<!-- version: 2 -->
|
||||||
|
|
||||||
# Usage de ksp-program-api
|
# Usage de ksp-program-api
|
||||||
|
|
||||||
Cette page décrit le scaffold public disponible à partir de `0.2.14-pre.002`. Utiliser uniquement les exports du crate-root ; aucun module interne ne fait partie du contrat consommable.
|
Cette page décrit la surface publique disponible à partir de `0.2.14-pre.003`. Utiliser uniquement les exports du crate-root ; aucun module interne ne fait partie du contrat consommable.
|
||||||
|
|
||||||
## Construire un input Program avec la façade
|
## Construire un input Program avec la façade
|
||||||
|
|
||||||
@@ -23,9 +23,61 @@ assert!(instruction.is_ok());
|
|||||||
|
|
||||||
`Pubkey`, `ProgramAccountMeta` et `ProgramInstruction` conservent leur ownership Core/Interface. Program API fournit seulement une façade cohérente aux futures implémentations de capability Program.
|
`Pubkey`, `ProgramAccountMeta` et `ProgramInstruction` conservent leur ownership Core/Interface. Program API fournit seulement une façade cohérente aux futures implémentations de capability Program.
|
||||||
|
|
||||||
|
## Représenter une reconnaissance
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let recognition = ksp_program_api::ProgramInstructionRecognition::ProgramMatch;
|
||||||
|
|
||||||
|
match recognition {
|
||||||
|
ksp_program_api::ProgramInstructionRecognition::NoMatch => {}
|
||||||
|
ksp_program_api::ProgramInstructionRecognition::ProgramMatch => {}
|
||||||
|
ksp_program_api::ProgramInstructionRecognition::ExactMatch => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Le wildcard est volontaire : l'enum est `#[non_exhaustive]` afin de ne pas transformer la foundation en vocabulaire fermé pour toujours.
|
||||||
|
|
||||||
|
## Représenter un outcome de décodage
|
||||||
|
|
||||||
|
Le type décodé reste possédé par l'implémentation :
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct ExternalDecodedInstruction {
|
||||||
|
opcode: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
let outcome = ksp_program_api::ProgramInstructionDecodeOutcome::Decoded(
|
||||||
|
ExternalDecodedInstruction { opcode: 7_u8 },
|
||||||
|
);
|
||||||
|
|
||||||
|
match outcome {
|
||||||
|
ksp_program_api::ProgramInstructionDecodeOutcome::Decoded(value) => {
|
||||||
|
assert_eq!(value.opcode, 7_u8);
|
||||||
|
}
|
||||||
|
ksp_program_api::ProgramInstructionDecodeOutcome::Unsupported => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Aucun `Any`, JSON ou enum centrale n'est nécessaire pour transporter ce type.
|
||||||
|
|
||||||
|
## Debug sûr
|
||||||
|
|
||||||
|
`ProgramInstructionDecodeOutcome<Decoded>` possède un `Debug` volontairement opaque sur la valeur décodée :
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct SecretDecoded;
|
||||||
|
|
||||||
|
let outcome = ksp_program_api::ProgramInstructionDecodeOutcome::Decoded(SecretDecoded);
|
||||||
|
assert_eq!(std::format!("{outcome:?}"), "Decoded");
|
||||||
|
```
|
||||||
|
|
||||||
|
`SecretDecoded` n'a même pas besoin d'implémenter `Debug`. Cela empêche un diagnostic générique de rendre accidentellement un payload externe.
|
||||||
|
|
||||||
## Utiliser le contrat d'erreur commun
|
## Utiliser le contrat d'erreur commun
|
||||||
|
|
||||||
Les types d'erreur Core sont également disponibles depuis la façade :
|
Les types d'erreur Core restent disponibles depuis la façade :
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn forward_result(
|
fn forward_result(
|
||||||
@@ -35,21 +87,20 @@ fn forward_result(
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Aucun type d'erreur Program spécifique n'est nécessaire au scaffold.
|
Le futur `decode(...)` utilisera ce `Result`. Une erreur sera donc `Err(...)`, tandis que `Unsupported` signifie une instruction connue volontairement non prise en charge.
|
||||||
|
|
||||||
## Ce que `pre.002` ne fournit pas
|
## Ce que `pre.003` ne fournit pas
|
||||||
|
|
||||||
Il n'existe encore aucun :
|
Il n'existe encore aucun :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
recognize(...)
|
|
||||||
decode(...)
|
|
||||||
ProgramInstructionRecognition
|
|
||||||
ProgramInstructionDecodeOutcome
|
|
||||||
ProgramInstructionDecoder
|
ProgramInstructionDecoder
|
||||||
|
program_ids(...)
|
||||||
|
recognize(...) sur un trait
|
||||||
|
decode(...) sur un trait
|
||||||
registry de decoders
|
registry de decoders
|
||||||
payload générique JSON/Any
|
payload générique JSON/Any
|
||||||
execution preparer
|
execution preparer
|
||||||
```
|
```
|
||||||
|
|
||||||
Ces éléments ne doivent pas être simulés côté consumer. Les contrats de recognition/outcome puis le trait decoder seront introduits dans leurs tranches dédiées.
|
Ces éléments ne doivent pas être simulés côté consumer. Le trait decoder et la preuve d'implémentation externe sont réservés à `pre.004`.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-program-api/src/lib.rs
|
// file: crates/ksp-program-api/src/lib.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![deny(unreachable_pub)]
|
#![deny(unreachable_pub)]
|
||||||
@@ -7,11 +7,17 @@
|
|||||||
|
|
||||||
//! Open Program contracts shared by KSP and external Program implementations.
|
//! Open Program contracts shared by KSP and external Program implementations.
|
||||||
//!
|
//!
|
||||||
//! This initial scaffold exposes only the Core and Interface types selected by
|
//! The foundation exposes Core/Interface types plus the minimal instruction
|
||||||
//! the `0.2.14` API model. Decoder behavior, recognition, decode outcomes,
|
//! recognition and decode-outcome vocabulary. Decoder behavior, registries,
|
||||||
//! registries, codecs, runtime logging and execution preparation are added only
|
//! codecs, runtime logging and execution preparation are added only by later
|
||||||
//! by later contracts when their ownership is justified.
|
//! contracts when their ownership is justified.
|
||||||
|
|
||||||
|
mod program_instruction_decode;
|
||||||
|
|
||||||
|
/// Result of a successful Program instruction decode attempt.
|
||||||
|
pub use self::program_instruction_decode::ProgramInstructionDecodeOutcome;
|
||||||
|
/// Recognition strength reported by one Program instruction implementation.
|
||||||
|
pub use self::program_instruction_decode::ProgramInstructionRecognition;
|
||||||
/// Common KSP error type used by Program-facing contracts.
|
/// Common KSP error type used by Program-facing contracts.
|
||||||
pub use ksp_core_lib::Error;
|
pub use ksp_core_lib::Error;
|
||||||
/// Stable structured code identifying a KSP error category and condition.
|
/// Stable structured code identifying a KSP error category and condition.
|
||||||
|
|||||||
50
crates/ksp-program-api/src/program_instruction_decode.rs
Normal file
50
crates/ksp-program-api/src/program_instruction_decode.rs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// file: crates/ksp-program-api/src/program_instruction_decode.rs
|
||||||
|
// version: 1
|
||||||
|
|
||||||
|
/// Recognition strength reported by one Program instruction implementation.
|
||||||
|
///
|
||||||
|
/// Recognition is intentionally instruction-local. It does not encode registry
|
||||||
|
/// priority, a persisted proof, a textual discriminator or a global Program
|
||||||
|
/// kind. [`Self::ExactMatch`] is an assertion made by the implementation for
|
||||||
|
/// the current instruction, while [`Self::ProgramMatch`] only establishes the
|
||||||
|
/// Program-level match.
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum ProgramInstructionRecognition {
|
||||||
|
/// The implementation does not claim the instruction.
|
||||||
|
NoMatch,
|
||||||
|
/// The Program or Program family matches, but the instruction is not proven exact.
|
||||||
|
ProgramMatch,
|
||||||
|
/// The implementation claims an exact instruction-local match.
|
||||||
|
ExactMatch,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Result of a successful Program instruction decode attempt.
|
||||||
|
///
|
||||||
|
/// Decode failures are represented by the surrounding KSP [`crate::Result`],
|
||||||
|
/// not by a parallel failure variant. `Unsupported` is reserved for a known
|
||||||
|
/// Program instruction that the implementation deliberately does not decode.
|
||||||
|
///
|
||||||
|
/// The custom [`std::fmt::Debug`] implementation never formats the `Decoded`
|
||||||
|
/// value, so external decoded payloads are not exposed accidentally through
|
||||||
|
/// generic diagnostics.
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum ProgramInstructionDecodeOutcome<Decoded> {
|
||||||
|
/// The instruction was decoded into the implementation-owned output type.
|
||||||
|
Decoded(Decoded),
|
||||||
|
/// The instruction is known but unsupported by this decode capability.
|
||||||
|
Unsupported,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Decoded> std::fmt::Debug for ProgramInstructionDecodeOutcome<Decoded> {
|
||||||
|
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Decoded(_) => return formatter.write_str("Decoded"),
|
||||||
|
Self::Unsupported => return formatter.write_str("Unsupported"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "../unit_tests/program_instruction_decode.rs"]
|
||||||
|
mod tests;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// file: crates/ksp-program-api/tests/dependency_boundary.rs
|
// file: crates/ksp-program-api/tests/dependency_boundary.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
//! Dependency and declarative-surface canaries for the Program API scaffold.
|
//! Dependency and declarative-surface canaries for the Program API foundation.
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pre_002_manifest_has_exact_core_and_interface_runtime_dependencies() {
|
fn pre_002_manifest_has_exact_core_and_interface_runtime_dependencies() {
|
||||||
@@ -46,23 +46,27 @@ fn pre_002_manifest_has_exact_core_and_interface_runtime_dependencies() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pre_002_crate_root_is_facade_only_without_decoder_runtime_surface() {
|
fn pre_003_crate_root_adds_only_recognition_and_decode_outcome() {
|
||||||
let crate_root = include_str!("../src/lib.rs");
|
let crate_root = include_str!("../src/lib.rs");
|
||||||
for required in ["Error", "ErrorCode", "ErrorContext", "Pubkey", "Result", "ProgramAccountMeta", "ProgramInstruction"] {
|
for required in [
|
||||||
|
"ProgramInstructionDecodeOutcome",
|
||||||
|
"ProgramInstructionRecognition",
|
||||||
|
"Error",
|
||||||
|
"ErrorCode",
|
||||||
|
"ErrorContext",
|
||||||
|
"Pubkey",
|
||||||
|
"Result",
|
||||||
|
"ProgramAccountMeta",
|
||||||
|
"ProgramInstruction",
|
||||||
|
] {
|
||||||
assert!(crate_root.contains(required), "required Program API facade export missing: {required}");
|
assert!(crate_root.contains(required), "required Program API facade export missing: {required}");
|
||||||
}
|
}
|
||||||
for forbidden in [
|
for forbidden in ["pub mod ", "ProgramInstructionDecoder", "ProgramExecutionPreparer", "TRACING_TARGET", "ksp_logging_lib", "serde", "Any"] {
|
||||||
"pub mod ",
|
assert!(!crate_root.contains(forbidden), "forbidden pre.003 Program API surface detected: {forbidden}");
|
||||||
"ProgramInstructionRecognition",
|
}
|
||||||
"ProgramInstructionDecodeOutcome",
|
let outcome_source = include_str!("../src/program_instruction_decode.rs");
|
||||||
"ProgramInstructionDecoder",
|
for forbidden in ["Ignored", "Failed", "serde", "Any"] {
|
||||||
"ProgramExecutionPreparer",
|
assert!(!outcome_source.contains(forbidden), "forbidden recognition/outcome concept detected: {forbidden}");
|
||||||
"TRACING_TARGET",
|
|
||||||
"ksp_logging_lib",
|
|
||||||
"serde",
|
|
||||||
"Any",
|
|
||||||
] {
|
|
||||||
assert!(!crate_root.contains(forbidden), "forbidden pre.002 Program API surface detected: {forbidden}");
|
|
||||||
}
|
}
|
||||||
assert!(!std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src/constants.rs").exists());
|
assert!(!std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("src/constants.rs").exists());
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// file: crates/ksp-program-api/tests/public_api.rs
|
// file: crates/ksp-program-api/tests/public_api.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
//! Integration canaries for the public `ksp-program-api` scaffold.
|
//! Integration canaries for the public `ksp-program-api` foundation.
|
||||||
|
|
||||||
fn consume_result(value: ksp_program_api::Result<ksp_program_api::Pubkey>) -> ksp_program_api::Result<ksp_program_api::Pubkey> {
|
fn consume_result(value: ksp_program_api::Result<ksp_program_api::Pubkey>) -> ksp_program_api::Result<ksp_program_api::Pubkey> {
|
||||||
return value;
|
return value;
|
||||||
@@ -31,3 +31,19 @@ fn public_pre_002_scaffold_does_not_require_private_modules() {
|
|||||||
assert!(!source.contains("pub mod "));
|
assert!(!source.contains("pub mod "));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn public_pre_003_recognition_and_decode_outcome_are_available_from_crate_root() {
|
||||||
|
let recognition = ksp_program_api::ProgramInstructionRecognition::ProgramMatch;
|
||||||
|
assert_eq!(std::format!("{recognition:?}"), "ProgramMatch");
|
||||||
|
let decoded = ksp_program_api::ProgramInstructionDecodeOutcome::Decoded(31_u16);
|
||||||
|
assert_eq!(std::format!("{decoded:?}"), "Decoded");
|
||||||
|
let decoded_value = match decoded {
|
||||||
|
ksp_program_api::ProgramInstructionDecodeOutcome::Decoded(value) => value,
|
||||||
|
_ => 0_u16,
|
||||||
|
};
|
||||||
|
assert_eq!(decoded_value, 31_u16);
|
||||||
|
let unsupported = ksp_program_api::ProgramInstructionDecodeOutcome::<u16>::Unsupported;
|
||||||
|
assert_eq!(std::format!("{unsupported:?}"), "Unsupported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// file: crates/ksp-program-api/unit_tests/program_instruction_decode.rs
|
||||||
|
// version: 1
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn recognition_variants_are_distinct_and_payload_free() {
|
||||||
|
assert_ne!(crate::ProgramInstructionRecognition::NoMatch, crate::ProgramInstructionRecognition::ProgramMatch);
|
||||||
|
assert_ne!(crate::ProgramInstructionRecognition::ProgramMatch, crate::ProgramInstructionRecognition::ExactMatch);
|
||||||
|
assert_eq!(std::format!("{:?}", crate::ProgramInstructionRecognition::NoMatch), "NoMatch");
|
||||||
|
assert_eq!(std::format!("{:?}", crate::ProgramInstructionRecognition::ProgramMatch), "ProgramMatch");
|
||||||
|
assert_eq!(std::format!("{:?}", crate::ProgramInstructionRecognition::ExactMatch), "ExactMatch");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decode_outcome_preserves_decoded_value_and_unsupported_state() {
|
||||||
|
let decoded = crate::ProgramInstructionDecodeOutcome::Decoded(17_u64);
|
||||||
|
let decoded_value = match decoded {
|
||||||
|
crate::ProgramInstructionDecodeOutcome::Decoded(value) => value,
|
||||||
|
crate::ProgramInstructionDecodeOutcome::Unsupported => 0_u64,
|
||||||
|
};
|
||||||
|
assert_eq!(decoded_value, 17_u64);
|
||||||
|
let unsupported = crate::ProgramInstructionDecodeOutcome::<u64>::Unsupported;
|
||||||
|
assert!(matches!(unsupported, crate::ProgramInstructionDecodeOutcome::Unsupported));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decode_outcome_debug_never_requires_or_renders_decoded_debug() {
|
||||||
|
struct ExternalDecoded {
|
||||||
|
secret_marker: u8,
|
||||||
|
}
|
||||||
|
let decoded = crate::ProgramInstructionDecodeOutcome::Decoded(ExternalDecoded { secret_marker: 0xA7_u8 });
|
||||||
|
assert_eq!(std::format!("{decoded:?}"), "Decoded");
|
||||||
|
let secret_marker = match decoded {
|
||||||
|
crate::ProgramInstructionDecodeOutcome::Decoded(value) => value.secret_marker,
|
||||||
|
crate::ProgramInstructionDecodeOutcome::Unsupported => 0_u8,
|
||||||
|
};
|
||||||
|
assert_eq!(secret_marker, 0xA7_u8);
|
||||||
|
assert_eq!(std::format!("{:?}", crate::ProgramInstructionDecodeOutcome::<ExternalDecoded>::Unsupported), "Unsupported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
285
deltas/0.2.14/pre.003.md
Normal file
285
deltas/0.2.14/pre.003.md
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
<!-- file: deltas/0.2.14/pre.003.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# Delta `0.2.14-pre.003` — recognition + outcome minimal
|
||||||
|
|
||||||
|
## 1. Base requise
|
||||||
|
|
||||||
|
Cette tranche s'applique exclusivement sur :
|
||||||
|
|
||||||
|
```text
|
||||||
|
v0.2.13
|
||||||
|
+ 0.2.14-pre.001
|
||||||
|
+ 0.2.14-pre.002
|
||||||
|
```
|
||||||
|
|
||||||
|
Le gate opérateur fourni pour `pre.002` est intégralement vert :
|
||||||
|
|
||||||
|
```text
|
||||||
|
cargo fmt --all PASS
|
||||||
|
python3 scripts/audit_rust_workspace_rules.py PASS
|
||||||
|
python3 scripts/audit_markdown_tables.py ... PASS — 170 tables / 119 fichiers
|
||||||
|
cargo check --workspace PASS
|
||||||
|
cargo clippy --workspace --all-targets PASS
|
||||||
|
cargo test -p ksp-program-api PASS
|
||||||
|
cargo test --workspace PASS
|
||||||
|
cargo tree -p ksp-program-api --edges normal PASS — Core + Interface uniquement
|
||||||
|
cargo tree --duplicates exécuté
|
||||||
|
```
|
||||||
|
|
||||||
|
La version workspace passe de :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.2.14-pre.2
|
||||||
|
```
|
||||||
|
|
||||||
|
à :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.2.14-pre.3
|
||||||
|
```
|
||||||
|
|
||||||
|
Commit attendu :
|
||||||
|
|
||||||
|
```text
|
||||||
|
v0.2.14-pre.003
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Objectif
|
||||||
|
|
||||||
|
Matérialiser uniquement le vocabulaire minimal nécessaire au futur decoder d'instruction :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ProgramInstructionRecognition
|
||||||
|
ProgramInstructionDecodeOutcome<Decoded>
|
||||||
|
```
|
||||||
|
|
||||||
|
La tranche ne crée toujours aucun comportement de décodage, registry ou contrat d'exécution.
|
||||||
|
|
||||||
|
## 3. Recognition
|
||||||
|
|
||||||
|
`ProgramInstructionRecognition` est public depuis le crate-root, `#[non_exhaustive]` et possède exactement :
|
||||||
|
|
||||||
|
```text
|
||||||
|
NoMatch
|
||||||
|
ProgramMatch
|
||||||
|
ExactMatch
|
||||||
|
```
|
||||||
|
|
||||||
|
Sémantique :
|
||||||
|
|
||||||
|
```text
|
||||||
|
NoMatch l'implémentation ne revendique pas l'instruction
|
||||||
|
ProgramMatch le Program ou la famille correspond sans preuve instruction-locale exacte
|
||||||
|
ExactMatch l'implémentation affirme un match instruction-local exact
|
||||||
|
```
|
||||||
|
|
||||||
|
Aucun score, priorité, confidence, proof, surface code ou discriminator textuel n'est introduit.
|
||||||
|
|
||||||
|
## 4. Decode outcome
|
||||||
|
|
||||||
|
`ProgramInstructionDecodeOutcome<Decoded>` est public depuis le crate-root, `#[non_exhaustive]` et possède exactement :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Decoded(Decoded)
|
||||||
|
Unsupported
|
||||||
|
```
|
||||||
|
|
||||||
|
La valeur `Decoded` reste possédée par l'implémentation future. Il n'existe aucun `Any`, JSON, payload D3 ou enum centrale pour l'effacer.
|
||||||
|
|
||||||
|
`Failed` est volontairement absent : le futur `ProgramInstructionDecoder::decode` retournera le `Result` Core. Une erreur réelle sera donc `Err`, sans deuxième canal de failure.
|
||||||
|
|
||||||
|
`Ignored` reste absent : une capability de décodage doit produire une valeur, déclarer l'instruction connue mais unsupported, ou échouer.
|
||||||
|
|
||||||
|
## 5. Debug sûr
|
||||||
|
|
||||||
|
`ProgramInstructionRecognition` ne transporte aucun payload.
|
||||||
|
|
||||||
|
`ProgramInstructionDecodeOutcome<Decoded>` possède une implémentation `Debug` manuelle :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Decoded(_) -> "Decoded"
|
||||||
|
Unsupported -> "Unsupported"
|
||||||
|
```
|
||||||
|
|
||||||
|
Cette implémentation :
|
||||||
|
|
||||||
|
```text
|
||||||
|
n'impose pas Decoded: Debug
|
||||||
|
ne formate jamais la valeur Decoded
|
||||||
|
ne copie aucun payload externe
|
||||||
|
reste bornée à un nom de variante fixe
|
||||||
|
```
|
||||||
|
|
||||||
|
Le test unitaire utilise volontairement un type externe sans implémentation `Debug` pour prouver cette propriété à la compilation.
|
||||||
|
|
||||||
|
## 6. Structure et façade
|
||||||
|
|
||||||
|
Un seul module privé est ajouté :
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/program_instruction_decode.rs
|
||||||
|
```
|
||||||
|
|
||||||
|
Le crate-root réexporte :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ProgramInstructionRecognition
|
||||||
|
ProgramInstructionDecodeOutcome
|
||||||
|
```
|
||||||
|
|
||||||
|
Aucun `pub mod` n'est introduit. Les réexports Core/Interface de `pre.002` restent inchangés.
|
||||||
|
|
||||||
|
## 7. Dependency firewall
|
||||||
|
|
||||||
|
Le manifest de `ksp-program-api` est inchangé :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ksp-core-lib
|
||||||
|
ksp-interface-lib
|
||||||
|
```
|
||||||
|
|
||||||
|
Restent interdits et absents :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ksp-program-lib
|
||||||
|
ksp-logging-lib
|
||||||
|
Transport / Config / Wallet / Store / Materializer
|
||||||
|
serde / serde_json
|
||||||
|
borsh / bincode / wincode
|
||||||
|
solana-instruction
|
||||||
|
reqwest / tokio / tonic / tauri / tracing
|
||||||
|
```
|
||||||
|
|
||||||
|
Aucun `constants.rs` ou `TRACING_TARGET` n'est justifié pour ces types déclaratifs.
|
||||||
|
|
||||||
|
## 8. Tests
|
||||||
|
|
||||||
|
### Unit
|
||||||
|
|
||||||
|
`unit_tests/program_instruction_decode.rs` vérifie :
|
||||||
|
|
||||||
|
```text
|
||||||
|
variants Recognition distincts
|
||||||
|
Debug Recognition exact et payload-free
|
||||||
|
Decoded conserve sa valeur
|
||||||
|
Unsupported reste distinct
|
||||||
|
Debug outcome sans Decoded: Debug
|
||||||
|
Debug outcome ne rend pas la valeur externe
|
||||||
|
```
|
||||||
|
|
||||||
|
### Public API
|
||||||
|
|
||||||
|
`tests/public_api.rs` ajoute un canari `pre.003` consommant uniquement :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ksp_program_api::ProgramInstructionRecognition
|
||||||
|
ksp_program_api::ProgramInstructionDecodeOutcome
|
||||||
|
```
|
||||||
|
|
||||||
|
### Boundary
|
||||||
|
|
||||||
|
`tests/dependency_boundary.rs` est avancé pour autoriser uniquement recognition/outcome tout en maintenant l'absence de trait decoder, preparer, logging, serde et module public.
|
||||||
|
|
||||||
|
## 9. Fichiers ajoutés
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/ksp-program-api/src/program_instruction_decode.rs
|
||||||
|
crates/ksp-program-api/unit_tests/program_instruction_decode.rs
|
||||||
|
deltas/0.2.14/pre.003.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 10. Fichiers modifiés
|
||||||
|
|
||||||
|
```text
|
||||||
|
Cargo.toml
|
||||||
|
crates/ksp-program-api/README.md
|
||||||
|
crates/ksp-program-api/USAGE.md
|
||||||
|
crates/ksp-program-api/src/lib.rs
|
||||||
|
crates/ksp-program-api/tests/dependency_boundary.rs
|
||||||
|
crates/ksp-program-api/tests/public_api.rs
|
||||||
|
docs/plans/021-V0_2_14_PROGRAM_API_PLAN.md
|
||||||
|
docs/validation/017-V0_2_14_PROGRAM_API.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 11. Fichiers volontairement inchangés
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/ksp-program-api/Cargo.toml
|
||||||
|
README.md
|
||||||
|
RULES.md
|
||||||
|
ROADMAP.md
|
||||||
|
CHANGELOG.md
|
||||||
|
docs/architecture/**
|
||||||
|
docs/rules/**
|
||||||
|
crates/ksp-core-lib/**
|
||||||
|
crates/ksp-interface-lib/**
|
||||||
|
crates/ksp-logging-lib/**
|
||||||
|
crates/ksp-*-transport-lib/**
|
||||||
|
crates/ksp-config-lib/**
|
||||||
|
crates/ksp-wallet-lib/**
|
||||||
|
crates/ksp-app-*/**
|
||||||
|
prompts/**
|
||||||
|
```
|
||||||
|
|
||||||
|
## 12. Scope négatif maintenu
|
||||||
|
|
||||||
|
Cette tranche n'introduit pas :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ProgramInstructionDecoder
|
||||||
|
program_ids(...)
|
||||||
|
recognize(...) sur un trait
|
||||||
|
decode(...) sur un trait
|
||||||
|
associated output contract du trait
|
||||||
|
external implementation fixture
|
||||||
|
registry runtime
|
||||||
|
identity/version/coverage
|
||||||
|
ProgramAccountDecoder / Event / ReturnData
|
||||||
|
payload canonique D3
|
||||||
|
ProgramExecutionPreparer
|
||||||
|
```
|
||||||
|
|
||||||
|
Ces éléments ne doivent pas être anticipés dans un fix de `pre.003`.
|
||||||
|
|
||||||
|
## 13. Gate opérateur attendu
|
||||||
|
|
||||||
|
Après application :
|
||||||
|
|
||||||
|
```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.2.14
|
||||||
|
cargo check --workspace
|
||||||
|
cargo clippy --workspace --all-targets
|
||||||
|
cargo test -p ksp-program-api
|
||||||
|
cargo test --workspace
|
||||||
|
cargo tree -p ksp-program-api --edges normal
|
||||||
|
cargo tree --duplicates
|
||||||
|
```
|
||||||
|
|
||||||
|
Le graphe normal doit rester :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ksp-program-api
|
||||||
|
├── ksp-core-lib
|
||||||
|
└── ksp-interface-lib
|
||||||
|
└── ksp-core-lib
|
||||||
|
```
|
||||||
|
|
||||||
|
Une correction découverte par ce gate reste un `0.2.14-pre.003-fix.NNN` et n'avance pas `pre.004`.
|
||||||
|
|
||||||
|
## 14. Suite
|
||||||
|
|
||||||
|
Après gate vert, `pre.004` pourra introduire uniquement :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ProgramInstructionDecoder: Send + Sync
|
||||||
|
associated type Decoded
|
||||||
|
program_ids(&self) -> &[Pubkey]
|
||||||
|
recognize(&self, &ProgramInstruction)
|
||||||
|
decode(&self, &ProgramInstruction) -> Result<ProgramInstructionDecodeOutcome<Self::Decoded>>
|
||||||
|
external implementation canary avec Pubkey non enregistré
|
||||||
|
```
|
||||||
|
|
||||||
|
Registry runtime, payload canonique D3 et `ProgramExecutionPreparer` resteront hors scope.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/plans/021-V0_2_14_PROGRAM_API_PLAN.md -->
|
<!-- file: docs/plans/021-V0_2_14_PROGRAM_API_PLAN.md -->
|
||||||
<!-- version: 2 -->
|
<!-- version: 3 -->
|
||||||
|
|
||||||
# Plan `0.2.14` — Program API foundation
|
# Plan `0.2.14` — Program API foundation
|
||||||
|
|
||||||
@@ -541,7 +541,7 @@ Baseline, règles/architecture, héritage, ownership, API candidate, dependency
|
|||||||
|
|
||||||
### `pre.002` — Scaffold `ksp-program-api` + façade + firewall
|
### `pre.002` — Scaffold `ksp-program-api` + façade + firewall
|
||||||
|
|
||||||
**Statut : matérialisé ; gate opérateur à confirmer.**
|
**Statut : réalisé ; gate opérateur intégralement PASS.**
|
||||||
|
|
||||||
La crate est membre du workspace avec exactement `ksp-core-lib` et `ksp-interface-lib` comme dépendances normales. Le crate-root réexporte `Error`, `ErrorCode`, `ErrorContext`, `Result`, `Pubkey`, `ProgramAccountMeta` et `ProgramInstruction`. README/USAGE initiaux et canaris `public_api` / `dependency_boundary` sont présents.
|
La crate est membre du workspace avec exactement `ksp-core-lib` et `ksp-interface-lib` comme dépendances normales. Le crate-root réexporte `Error`, `ErrorCode`, `ErrorContext`, `Result`, `Pubkey`, `ProgramAccountMeta` et `ProgramInstruction`. README/USAGE initiaux et canaris `public_api` / `dependency_boundary` sont présents.
|
||||||
|
|
||||||
@@ -549,7 +549,9 @@ Aucun trait decoder, recognition, outcome, registry, codec, runtime logging ou e
|
|||||||
|
|
||||||
### `pre.003` — Recognition + outcome minimal
|
### `pre.003` — Recognition + outcome minimal
|
||||||
|
|
||||||
Introduire `ProgramInstructionRecognition` et `ProgramInstructionDecodeOutcome<Decoded>` avec invariants et Debug sûr. Aucun descriptor/registry.
|
**Statut : matérialisé ; gate opérateur à confirmer.**
|
||||||
|
|
||||||
|
`ProgramInstructionRecognition` et `ProgramInstructionDecodeOutcome<Decoded>` sont ajoutés dans un module privé puis réexportés depuis le crate-root. Les deux enums sont `#[non_exhaustive]`. Le `Debug` de l'outcome est manuel, ne requiert pas `Decoded: Debug` et n'affiche jamais la valeur décodée. Aucun descriptor, registry ou trait decoder n'est avancé.
|
||||||
|
|
||||||
### `pre.004` — `ProgramInstructionDecoder` + external implementation
|
### `pre.004` — `ProgramInstructionDecoder` + external implementation
|
||||||
|
|
||||||
@@ -599,6 +601,27 @@ dependency firewall canary présent
|
|||||||
|
|
||||||
`pre.003` reste limité à `ProgramInstructionRecognition` et `ProgramInstructionDecodeOutcome<Decoded>` avec leur sémantique et leur Debug sûr. Le trait decoder reste réservé à `pre.004`.
|
`pre.003` reste limité à `ProgramInstructionRecognition` et `ProgramInstructionDecodeOutcome<Decoded>` avec leur sémantique et leur Debug sûr. Le trait decoder reste réservé à `pre.004`.
|
||||||
|
|
||||||
|
## 13.2 État préparé après `pre.003`
|
||||||
|
|
||||||
|
Le gate opérateur `pre.002` fourni le 28 août 2026 est intégralement vert : audits Rust/Markdown, check, Clippy, tests de `ksp-program-api`, workspace complet et graphes Cargo ont été exécutés. Le graphe normal ciblé reste exactement `Core + Interface`.
|
||||||
|
|
||||||
|
La tranche `pre.003` matérialise :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ProgramInstructionRecognition NoMatch / ProgramMatch / ExactMatch
|
||||||
|
ProgramInstructionDecodeOutcome<T> Decoded(T) / Unsupported
|
||||||
|
non_exhaustive oui sur les deux enums
|
||||||
|
Debug recognition payload-free par construction
|
||||||
|
Debug outcome opaque, sans bound T: Debug
|
||||||
|
Failed / Ignored absents
|
||||||
|
priority / confidence / proof absents de la surface
|
||||||
|
ProgramInstructionDecoder absent par contrat pre.003
|
||||||
|
registry / canonical payload / preparer absents
|
||||||
|
normal dependencies inchangées : Core + Interface
|
||||||
|
```
|
||||||
|
|
||||||
|
Les tests unitaires vérifient notamment qu'un type décodé externe dépourvu de `Debug` peut être contenu et formaté via l'outcome sans exposer sa valeur. Le passage à `pre.004` reste conditionné au gate opérateur de cet overlay.
|
||||||
|
|
||||||
## 14. Hors périmètre confirmé
|
## 14. Hors périmètre confirmé
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/validation/017-V0_2_14_PROGRAM_API.md -->
|
<!-- file: docs/validation/017-V0_2_14_PROGRAM_API.md -->
|
||||||
<!-- version: 2 -->
|
<!-- version: 3 -->
|
||||||
|
|
||||||
# Validation `0.2.14` — Program API foundation
|
# Validation `0.2.14` — Program API foundation
|
||||||
|
|
||||||
@@ -37,8 +37,8 @@ Le scope validé par `pre.001` est une foundation instruction-only avec output a
|
|||||||
|
|
||||||
| Contrat | Décision `pre.001` | Gate futur |
|
| Contrat | Décision `pre.001` | Gate futur |
|
||||||
|--------------------------------------------|---------------------------------------------------------|--------------------------------|
|
|--------------------------------------------|---------------------------------------------------------|--------------------------------|
|
||||||
| `ProgramInstructionRecognition` | `NoMatch / ProgramMatch / ExactMatch`, non exhaustif | `pre.003` |
|
| `ProgramInstructionRecognition` | `NoMatch / ProgramMatch / ExactMatch`, non exhaustif | PASS `pre.003` |
|
||||||
| `ProgramInstructionDecodeOutcome<Decoded>` | `Decoded(Decoded) / Unsupported`, non exhaustif | `pre.003` |
|
| `ProgramInstructionDecodeOutcome<Decoded>` | `Decoded(Decoded) / Unsupported`, non exhaustif | PASS `pre.003` |
|
||||||
| decoder failure | `ksp_core_lib::Result`, aucun statut `Failed` parallèle | `pre.003` / `pre.004` |
|
| decoder failure | `ksp_core_lib::Result`, aucun statut `Failed` parallèle | `pre.003` / `pre.004` |
|
||||||
| `ProgramInstructionDecoder` | `Send + Sync`, associated `Decoded` | `pre.004` |
|
| `ProgramInstructionDecoder` | `Send + Sync`, associated `Decoded` | `pre.004` |
|
||||||
| input | `&ProgramInstruction` | `pre.004` |
|
| input | `&ProgramInstruction` | `pre.004` |
|
||||||
@@ -105,8 +105,8 @@ tracing
|
|||||||
| unknown Program Pubkey | utilisable sans registry Core | PENDING |
|
| unknown Program Pubkey | utilisable sans registry Core | PENDING |
|
||||||
| max Interface input | decoder consomme l'input déjà borné sans nouvelle allocation obligatoire | PENDING |
|
| max Interface input | decoder consomme l'input déjà borné sans nouvelle allocation obligatoire | PENDING |
|
||||||
| malformed program payload | `Err` ou `Unsupported` selon contrat, sans payload dans l'erreur | PENDING |
|
| malformed program payload | `Err` ou `Unsupported` selon contrat, sans payload dans l'erreur | PENDING |
|
||||||
| Debug recognition | aucun payload | PENDING |
|
| Debug recognition | aucun payload | PASS |
|
||||||
| Debug outcome | contenu `Decoded` non rendu automatiquement | PENDING |
|
| Debug outcome | contenu `Decoded` non rendu automatiquement | PASS |
|
||||||
| default methods | aucun default method susceptible de masquer panic/policy | PENDING |
|
| default methods | aucun default method susceptible de masquer panic/policy | PENDING |
|
||||||
| closed-world enum | aucun inventaire central de Program kinds | PENDING |
|
| closed-world enum | aucun inventaire central de Program kinds | PENDING |
|
||||||
| serde accidental | aucune dependency/derive | PENDING |
|
| serde accidental | aucune dependency/derive | PENDING |
|
||||||
@@ -157,25 +157,37 @@ prompt de démarrage 0.3.1
|
|||||||
delta de la prerelease
|
delta de la prerelease
|
||||||
```
|
```
|
||||||
|
|
||||||
## 8. État préparé `pre.002`
|
## 8. Gate opérateur `pre.002`
|
||||||
|
|
||||||
Le scaffold matérialisé est :
|
Le gate fourni le 28 août 2026 est intégralement vert :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
workspace member PASS structurel
|
cargo fmt --all PASS
|
||||||
normal dependencies ksp-core-lib + ksp-interface-lib uniquement
|
audit Rust général / exports / workspace PASS
|
||||||
crate-root facade Error/ErrorCode/ErrorContext/Result/Pubkey + Interface instruction types
|
audit Markdown PASS — 170 tables / 119 fichiers
|
||||||
public modules aucun
|
cargo check --workspace PASS
|
||||||
README / USAGE présents
|
cargo clippy --workspace --all-targets PASS
|
||||||
public API canary présent
|
cargo test -p ksp-program-api PASS — 4 tests d'intégration
|
||||||
dependency firewall canary présent
|
cargo test --workspace PASS
|
||||||
ProgramInstructionRecognition absent par contrat pre.002
|
cargo tree -p ksp-program-api --edges normal PASS — Core + Interface uniquement
|
||||||
ProgramInstructionDecodeOutcome absent par contrat pre.002
|
cargo tree --duplicates exécuté, inventaire workspace observé
|
||||||
ProgramInstructionDecoder absent par contrat pre.002
|
|
||||||
registry / canonical payload / preparer absents
|
|
||||||
serde / codecs / runtime logging absents
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Le gate opérateur `pre.001` fourni le 28 août 2026 est vert pour `cargo fmt --all`, audits Rust/Markdown, `cargo check --workspace` et Clippy workspace.
|
Ce gate autorise l'ouverture de `pre.003`.
|
||||||
|
|
||||||
Le passage à `pre.003` reste conditionné au gate opérateur de cet overlay. Les preuves recognition/outcome restent `PENDING` jusqu'à leur tranche dédiée.
|
## 9. État préparé `pre.003`
|
||||||
|
|
||||||
|
| Critère | Statut | Preuve |
|
||||||
|
|--------------------------------------|--------|----------------------------------------------------------------------|
|
||||||
|
| `ProgramInstructionRecognition` | PASS | enum non exhaustif `NoMatch / ProgramMatch / ExactMatch` |
|
||||||
|
| `ProgramInstructionDecodeOutcome<T>` | PASS | enum non exhaustif `Decoded(T) / Unsupported` |
|
||||||
|
| absence de `Failed` / `Ignored` | PASS | échec réservé au futur `Result`; aucun statut parallèle |
|
||||||
|
| Debug recognition | PASS | enum sans payload; Debug dérivé |
|
||||||
|
| Debug outcome | PASS | implémentation manuelle sans `T: Debug`, valeur `Decoded` non rendue |
|
||||||
|
| dépendances normales | PASS | manifest inchangé : `ksp-core-lib` + `ksp-interface-lib` |
|
||||||
|
| module public | PASS | aucun `pub mod`; exports crate-root uniquement |
|
||||||
|
| `ProgramInstructionDecoder` | ABSENT | réservé à `pre.004` |
|
||||||
|
| registry / descriptor / payload D3 | ABSENT | hors scope maintenu |
|
||||||
|
| serde / codec / logging / runtime | ABSENT | dependency firewall maintenu |
|
||||||
|
|
||||||
|
Les canaris unitaires et publics de `pre.003` doivent passer avant d'ouvrir `pre.004`. La preuve d'implémentation externe, le Program Pubkey open-world et l'associated output complet restent réservés au trait decoder de la tranche suivante.
|
||||||
|
|||||||
Reference in New Issue
Block a user