ri-esp-proof 0.1.1

no_std proof/receipt crate for ESP32/S3: sensor reading + sentinel confidence -> routing decision -> JSON receipt
Documentation
use ri_esp_core::EnvironmentReading;
use ri_esp_policy::{PolicyContext, PromptId};
use ri_esp_proof::{ProofConfig, ProofDecision, ProofEngine, RouteReason};

#[test]
fn low_confidence_sensor_context_forwards_to_ai() {
    let mut engine = ProofEngine::new(ProofConfig::default());
    let sensor = EnvironmentReading::new(29.5, 71.0, Some(31.0));

    let receipt = engine.evaluate("esp32-proof-01", 42_000, sensor, 0.42, "gtx1070-local");

    assert_eq!(receipt.event_id, 1);
    assert_eq!(receipt.decision, ProofDecision::ForwardToAi);
    assert_eq!(receipt.reason.as_str(), "low_confidence");
    assert_eq!(receipt.sensor.temperature_c, Some(29.5));
}

#[test]
fn healthy_confidence_and_normal_environment_stays_local() {
    let mut engine = ProofEngine::new(ProofConfig::default());
    let sensor = EnvironmentReading::new(22.0, 45.0, Some(21.9));

    let receipt = engine.evaluate("esp32-proof-01", 43_000, sensor, 0.91, "gtx1070-local");

    assert_eq!(receipt.event_id, 1);
    assert_eq!(receipt.decision, ProofDecision::LocalOnly);
    assert_eq!(receipt.reason.as_str(), "local_confident");
}

#[test]
fn receipt_json_contains_sensor_ai_route_and_decision() {
    let mut engine = ProofEngine::new(ProofConfig::default());
    let sensor = EnvironmentReading::new(12.0, 45.0, None);
    let receipt = engine.evaluate("esp32-proof-01", 44_000, sensor, 0.92, "gtx1070-local");

    let json = receipt.to_json::<768>().unwrap();

    assert!(json.contains("\"device_id\":\"esp32-proof-01\""));
    assert!(json.contains("\"decision\":\"forward_to_ai\""));
    assert!(json.contains("\"reason\":\"temperature_out_of_range\""));
    assert!(json.contains("\"temperature_c\":12"));
    assert!(json.contains("\"ai_route\":\"gtx1070-local\""));
}

#[test]
fn feature_transfer_payload_is_available_for_gpu_forwarding() {
    let mut engine = ProofEngine::new(ProofConfig::default());
    let sensor = EnvironmentReading::new(29.5, 71.0, Some(31.0));
    let receipt = engine.evaluate("esp32-proof-01", 42_000, sensor, 0.42, "gtx1070-local");

    let transfer = receipt.to_feature_transfer::<4>().unwrap();

    assert!(transfer.should_wake(0.75));
    assert_eq!(transfer.features.len(), 3);
    assert_eq!(transfer.features[0], 29.5);
    assert_eq!(transfer.features[1], 71.0);
    assert_eq!(transfer.features[2], 31.0);
}

#[test]
fn policy_evaluation_records_s3_local_language_fields() {
    let mut engine = ProofEngine::new(ProofConfig::default());
    let sensor = EnvironmentReading::new(31.0, 70.0, None);
    let ctx = PolicyContext::new(sensor, 3_000).with_last_read_ms(2_900);

    let receipt = engine.evaluate_with_policy("esp32-proof-01", ctx, "gtx1070-local");

    assert_eq!(
        receipt.route_reason,
        RouteReason::TemperatureAndHumidityOutOfRange
    );
    assert_eq!(
        receipt.local_language_model.as_str(),
        "esp32s3-h320-p15-char-lstm"
    );
    assert_eq!(
        receipt.local_language_prompt.as_str(),
        PromptId::HighHeatHumidity.prompt_text()
    );
    let json = receipt.to_json::<1024>().unwrap();
    assert!(json.contains("\"local_language_model\":\"esp32s3-h320-p15-char-lstm\""));
    assert!(json.contains("\"local_language_prompt\":\"high heat and humidity. action is \""));
}

#[test]
fn policy_evaluation_records_stale_route() {
    let mut engine = ProofEngine::new(ProofConfig::default());
    let sensor = EnvironmentReading::new(22.0, 42.0, None);
    let ctx = PolicyContext::new(sensor, 500_000).with_last_read_ms(100_000);

    let receipt = engine.evaluate_with_policy("esp32-proof-01", ctx, "gtx1070-local");

    assert_eq!(receipt.route_reason, RouteReason::StaleReading);
    assert_eq!(receipt.decision, ProofDecision::ForwardToAi);
    assert_eq!(
        receipt.local_language_prompt.as_str(),
        "stale data. action is "
    );
}

#[test]
fn policy_evaluation_keeps_cold_dry_on_safe_prompt() {
    let mut engine = ProofEngine::new(ProofConfig::default());
    let sensor = EnvironmentReading::new(14.0, 45.0, None);
    let ctx = PolicyContext::new(sensor, 5_500).with_last_read_ms(5_400);

    let receipt = engine.evaluate_with_policy("esp32-proof-01", ctx, "gtx1070-local");

    assert_eq!(receipt.local_language_prompt.as_str(), "safe action is ");
    assert_eq!(receipt.route_reason, RouteReason::UnsupportedColdOrDry);
}