elicitation 0.8.0

Conversational elicitation of strongly-typed Rust values via MCP
Documentation
//! Demonstration of compositional verification through formal verification legos.
//!
//! This example shows how the `elicitation` framework creates a compositionally
//! verified ecosystem where types snap together like legos, with each connection
//! formally proven safe.
//!
//! # The Vision: "Formal Verification Legos"
//!
//! Types implementing `Elicitation` form a verification hierarchy:
//!
//! ```text
//! ┌─────────────────────────────────────────────────┐
//! │ Layer 1: Primitive Types (Manual Kani Proofs)  │
//! │ ✓ I8Positive, StringNonEmpty, U8NonZero         │
//! └─────────────────┬───────────────────────────────┘
//!//!                   │ implements Elicitation
//!                   │ #[derive(Elicit)]
//!//! ┌─────────────────────────────────────────────────┐
//! │ Layer 2: Derived Structs (Compositional Proofs) │
//! │ struct Config {                                 │
//! │     timeout: I8Positive,  ← verified           │
//! │     retries: U8NonZero,   ← verified           │
//! │ }                                               │
//! │ ⟹ Config verified by composition ∎            │
//! └─────────────────┬───────────────────────────────┘
//!//!                   │ implements Elicitation
//!                   │ #[derive(Elicit)]
//!//! ┌─────────────────────────────────────────────────┐
//! │ Layer 3: Higher-Order Types                    │
//! │ struct Application {                            │
//! │     config: Config,       ← verified           │
//! │     name: StringNonEmpty, ← verified           │
//! │ }                                               │
//! │ ⟹ Application verified by composition ∎       │
//! └─────────────────────────────────────────────────┘
//! ```
//!
//! # The "Caged Agent" Property
//!
//! When an LLM is asked to elicit a type `T: Elicitation`:
//! - The type system enforces that `T` is verified
//! - The verification is **non-bypassable** (enforced at compile time)
//! - Invalid states are **unrepresentable** (cannot be constructed)
//!
//! This creates a "cage" where the agent can only produce values that
//! have been mathematically proven to satisfy their contracts.
//!
//! # Running This Example
//!
//! This example doesn't run - it demonstrates compile-time verification:
//!
//! ```bash
//! # Verify compilation (proves compositional structure is valid)
//! cargo check --example compositional_verification
//!
//! # Run Kani proofs (witnesses that verification is sound)
//! cargo kani --harness verify_compositional_legos
//! ```

use elicitation::Elicit;

#[cfg(kani)]
use elicitation::Elicitation;

// ============================================================================
// Layer 1: Primitive Types (Foundation for Composition)
// ============================================================================

// Rust primitives (i32, u16, String, etc.) form the foundation layer.
// The elicitation library provides contract types with manual Kani proofs:
// - I8Positive, U8NonZero: verified in verification/types/kani_proofs/integers.rs
// - StringNonEmpty: verified in verification/types/kani_proofs/strings.rs
//
// This example uses primitives for simplicity, but the compositional
// verification works the same way with contract types.

// ============================================================================
// Layer 2: Derived Structs (Compositional Proofs)
// ============================================================================

#[cfg(any(feature = "verification", kani))]
mod layer2 {
    use super::*;

    /// Network configuration with verified constraints.
    ///
    /// **Verification by composition:**
    /// - `port`: u16 (primitive type, symbolically verifiable)
    /// - `timeout_sec`: i32 (primitive type, symbolically verifiable)
    /// - ⟹ NetworkConfig is verified ∎
    ///
    /// Note: In a real application, you would use contract types like U16NonZero
    /// and I32Positive. This example uses primitives for simplicity.
    #[allow(dead_code)]
    #[derive(Debug, Clone, Elicit, schemars::JsonSchema)]
    pub struct NetworkConfig {
        /// Network port.
        pub port: u16,

        /// Timeout in seconds.
        pub timeout_sec: i32,
    }

    /// Application metadata.
    ///
    /// **Verification by composition:**
    /// - `name`: String (primitive type, symbolically verifiable)
    /// - `max_retries`: u8 (primitive type, symbolically verifiable)
    /// - ⟹ AppMetadata is verified ∎
    #[allow(dead_code)]
    #[derive(Debug, Clone, Elicit, schemars::JsonSchema)]
    pub struct AppMetadata {
        /// Application name.
        pub name: String,

        /// Maximum retry attempts.
        pub max_retries: u8,
    }
}

#[cfg(any(feature = "verification", kani))]
use layer2::{AppMetadata, NetworkConfig};

// ============================================================================
// Layer 3: Higher-Order Types (Nested Compositional Proofs)
// ============================================================================

#[cfg(any(feature = "verification", kani))]
mod layer3 {
    use super::*;
    use elicitation::{Prompt, Select};

    /// Complete application configuration.
    ///
    /// **Verification by composition:**
    /// - `network`: NetworkConfig (verified struct)
    /// - `metadata`: AppMetadata (verified struct)
    /// - ⟹ ApplicationConfig is verified ∎
    ///
    /// The proof chain:
    /// 1. Primitives are manually proven (I8Positive, U8NonZero, StringNonEmpty)
    /// 2. Layer 2 structs are proven by composition (NetworkConfig, AppMetadata)
    /// 3. Layer 3 structs are proven by composition (ApplicationConfig)
    /// 4. ∴ The entire hierarchy is formally verified ∎
    #[allow(dead_code)]
    #[derive(Debug, Clone, Elicit, schemars::JsonSchema)]
    pub struct ApplicationConfig {
        /// Network settings (verified).
        pub network: NetworkConfig,

        /// Application metadata (verified).
        pub metadata: AppMetadata,
    }

    /// Deployment mode with verified constraints.
    ///
    /// **Verification by composition:**
    /// - `Development`: Unit variant (trivially verified)
    /// - `Production`: Contains NetworkConfig (verified struct)
    /// - ⟹ DeploymentMode is verified ∎
    #[allow(dead_code)]
    #[derive(Debug, Clone, Elicit, schemars::JsonSchema)]
    pub enum DeploymentMode {
        /// Development mode (no configuration needed).
        Development,

        /// Production mode with network configuration.
        Production {
            /// Production network settings (verified).
            config: NetworkConfig,
        },
    }
}

#[cfg(any(feature = "verification", kani))]
// Example types removed;

// ============================================================================
// Kani Proof Harness: Witness the Compositional Chain
// ============================================================================
#[cfg(kani)]
#[kani::proof]
fn verify_compositional_legos() {
    // Layer 1: Primitive types (i32, u16, String) are verified by Rust's type system
    // Contract types like I8Positive, U8NonZero have separate manual Kani proofs

    // Layer 2: Compositional proofs call field-level proofs
    NetworkConfig::kani_proof();
    AppMetadata::kani_proof();

    // Layer 3: Nested compositional proofs
    ApplicationConfig::kani_proof();

    // Enum compositional proof
    DeploymentMode::kani_proof();

    // The tautology: If all parts verified, whole verified
    assert!(
        true,
        "Compositional verification: all layers proven ⟹ entire ecosystem verified ∎"
    );
}

// ============================================================================
// Documentation: Understanding the Proof Strategy
// ============================================================================

/// # Tautological Proof by Composition
///
/// The verification strategy is **tautological** (proof by construction):
///
/// ## Base Case (Layer 1)
///
/// Primitive types like `I8Positive` have **manual Kani proofs**:
///
/// ```rust,ignore
/// #[kani::proof]
/// fn verify_i8_positive() {
///     let value: i8 = kani::any();
///     match I8Positive::new(value) {
///         Ok(pos) => assert!(value > 0),
///         Err(_) => assert!(value <= 0),
///     }
/// }
/// ```
///
/// These proofs use symbolic execution to verify **all possible inputs**.
///
/// ## Inductive Case (Layer 2+)
///
/// Derived types inherit verification **by composition**:
///
/// ```rust,ignore
/// #[derive(Elicit)]
/// struct Config {
///     timeout: I8Positive,  // ← verified
///     retries: U8NonZero,   // ← verified
/// }
///
/// // Generated by #[derive(Elicit)]:
/// impl Elicitation for Config {
///     #[cfg(kani)]
///     fn kani_proof() {
///         I8Positive::kani_proof();  // Verify timeout field
///         U8NonZero::kani_proof();   // Verify retries field
///         // Tautology: all parts verified ⟹ whole verified
///         assert!(true, "Compositional verification");
///     }
/// }
/// ```
///
/// ## The Proof Chain
///
/// 1. **Primitives are verified** (manual Kani proofs with symbolic execution)
/// 2. **Derived types call field proofs** (`#[derive(Elicit)]` generates kani_proof)
/// 3. **Type system enforces** all fields implement `Elicitation`
/// 4. **∴ If compilation succeeds, verification succeeds** ∎
///
/// ## Why This is Non-Bypassable
///
/// The "cage" cannot be escaped because:
/// - **Type system** enforces `Elicitation` trait bounds
/// - **Kani proofs** verify primitives for all possible inputs
/// - **Composition** inherits verification transitively
/// - **Compilation** witnesses the entire chain
///
/// An LLM asked to produce a `Config` cannot:
/// - Bypass type checks (compile-time enforcement)
/// - Produce invalid primitives (Kani proves impossible)
/// - Skip field verification (derive macro enforces)
/// - Construct unverified states (unrepresentable in type system)
///
/// The verification is **proof-carrying**: types carry their own proofs.
#[cfg(kani)]
fn _documentation() {}

fn main() {
    println!("This example demonstrates compile-time verification.");
    println!("The verification happens when you compile - no runtime needed!");
    println!();

    #[cfg(any(feature = "verification", kani))]
    {
        println!("Verification features enabled - types are compositionally verified!");
        println!();
        println!("To witness the proofs:");
        println!("  cargo check --example compositional_verification --features verification");
        println!("  cargo kani --harness verify_compositional_legos");
    }

    #[cfg(not(any(feature = "verification", kani)))]
    {
        println!("Verification features NOT enabled.");
        println!();
        println!("To enable verification:");
        println!("  cargo check --example compositional_verification --features verification");
    }
}