polyc-state-connect 2026.9.0

State plane transport adapter: capability-specific Connect clients and server-trait glue mapping the generated wire types onto the polyc-state kernel — typed outcomes, per-call admission, and the conformance surface the authenticated shell proves itself against (docs/proposals/separated-planes.md).
use polyc_proto::proto::polychrome::state::v1 as pb;
use polyc_state::{
    command::FencingToken,
    digest::ContentDigest,
    id::AttemptId,
    model_attempt::{
        ModelAttemptLifecycle, ModelAttemptReceipt, ModelAttemptRequest, ModelConversationId,
        ModelPurpose, TenantId,
    },
};

use crate::wire::{fixed_bytes, malformed};

pub(crate) fn request_to_wire(value: &ModelAttemptRequest) -> pb::StateModelAttemptRequest {
    pb::StateModelAttemptRequest {
        tenant: value.tenant().as_str().to_owned(),
        conversation: value.conversation().as_str().to_owned(),
        execution: value.execution().to_owned(),
        claim_attempt: value.claim_attempt().as_str().to_owned(),
        fence: value.fence().get(),
        transport_attempt: value.transport_attempt().as_str().to_owned(),
        model_attempt: value.model_attempt().as_str().to_owned(),
        purpose: value.purpose().as_str().to_owned(),
        request_digest: value.request_digest().as_bytes().to_vec(),
        __buffa_unknown_fields: buffa::UnknownFields::default(),
    }
}

pub(crate) fn request_from_wire(
    value: pb::StateModelAttemptRequest,
) -> Result<ModelAttemptRequest, polyc_state::error::StateError> {
    let purpose = match value.purpose.as_str() {
        "answering" => ModelPurpose::Answering,
        "summarization" => ModelPurpose::Summarization,
        "classification" => ModelPurpose::Classification,
        _ => return Err(malformed("purpose", "unknown model-attempt purpose")),
    };
    Ok(ModelAttemptRequest::new(
        TenantId::new(value.tenant),
        ModelConversationId::new(value.conversation),
        value.execution,
        AttemptId::new(value.claim_attempt),
        FencingToken::new(value.fence),
        AttemptId::new(value.transport_attempt),
        AttemptId::new(value.model_attempt),
        purpose,
        ContentDigest::from_bytes(fixed_bytes("request_digest", &value.request_digest)?),
    ))
}

pub(crate) const fn lifecycle_to_wire(
    value: ModelAttemptLifecycle,
) -> pb::StateModelAttemptLifecycle {
    match value {
        ModelAttemptLifecycle::Reserved => {
            pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_RESERVED
        }
        ModelAttemptLifecycle::Dispatched => {
            pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_DISPATCHED
        }
        ModelAttemptLifecycle::SettledSuccess => {
            pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_SETTLED_SUCCESS
        }
        ModelAttemptLifecycle::SettledKnownFailure => {
            pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_SETTLED_KNOWN_FAILURE
        }
        ModelAttemptLifecycle::Ambiguous => {
            pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_AMBIGUOUS
        }
        ModelAttemptLifecycle::Quarantined => {
            pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_QUARANTINED
        }
        ModelAttemptLifecycle::ReconciledSuccess => {
            pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_RECONCILED_SUCCESS
        }
        ModelAttemptLifecycle::ReconciledFailure => {
            pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_RECONCILED_FAILURE
        }
    }
}

pub(crate) fn lifecycle_from_wire(
    value: buffa::EnumValue<pb::StateModelAttemptLifecycle>,
) -> Result<ModelAttemptLifecycle, polyc_state::error::StateError> {
    match value.as_known() {
        Some(pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_RESERVED) => {
            Ok(ModelAttemptLifecycle::Reserved)
        }
        Some(pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_DISPATCHED) => {
            Ok(ModelAttemptLifecycle::Dispatched)
        }
        Some(pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_SETTLED_SUCCESS) => {
            Ok(ModelAttemptLifecycle::SettledSuccess)
        }
        Some(
            pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_SETTLED_KNOWN_FAILURE,
        ) => Ok(ModelAttemptLifecycle::SettledKnownFailure),
        Some(pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_AMBIGUOUS) => {
            Ok(ModelAttemptLifecycle::Ambiguous)
        }
        Some(pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_QUARANTINED) => {
            Ok(ModelAttemptLifecycle::Quarantined)
        }
        Some(pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_RECONCILED_SUCCESS) => {
            Ok(ModelAttemptLifecycle::ReconciledSuccess)
        }
        Some(pb::StateModelAttemptLifecycle::STATE_MODEL_ATTEMPT_LIFECYCLE_RECONCILED_FAILURE) => {
            Ok(ModelAttemptLifecycle::ReconciledFailure)
        }
        _ => Err(malformed("lifecycle", "unknown model-attempt lifecycle")),
    }
}

pub(crate) fn receipt_to_wire(value: &ModelAttemptReceipt) -> pb::StateModelAttemptReceipt {
    pb::StateModelAttemptReceipt {
        version: u32::from(value.version()),
        request: buffa::MessageField::some(request_to_wire(value.request())),
        lifecycle: buffa::EnumValue::Known(lifecycle_to_wire(value.lifecycle())),
        __buffa_unknown_fields: buffa::UnknownFields::default(),
    }
}

pub(crate) fn receipt_from_wire(
    value: pb::StateModelAttemptReceipt,
) -> Result<ModelAttemptReceipt, polyc_state::error::StateError> {
    let request = value
        .request
        .into_option()
        .ok_or_else(|| malformed("request", "model-attempt receipt requires request"))?;
    let version = u16::try_from(value.version)
        .map_err(|_| malformed("version", "model-attempt version exceeds u16"))?;
    ModelAttemptReceipt::from_parts(
        version,
        request_from_wire(request)?,
        lifecycle_from_wire(value.lifecycle)?,
    )
    .map_err(|error| malformed("receipt", error.to_string()))
}