cordance-llm 0.1.1

Cordance LLM adapters. Bounded candidate prose only. No hard rules from LLM.
Documentation
//! `cordance-llm-candidate.v1` schema.

use serde::{Deserialize, Serialize};

pub const SCHEMA: &str = "cordance-llm-candidate.v1";

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct LlmCandidate {
    pub schema: String,
    pub candidate_id: String,
    /// Source IDs from the pack that this candidate was given as context.
    pub input_source_ids: Vec<String>,
    pub claims: Vec<LlmClaim>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct LlmClaim {
    pub text: String,
    pub claim_type: ClaimType,
    /// Every source ID here must be present in `input_source_ids`.
    pub source_ids: Vec<String>,
    pub confidence: ClaimConfidence,
}

/// ADR 0002: `hard_rule` and `project_invariant` cannot originate from LLM output.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ClaimType {
    WorkflowInstruction,
    StrongPreference,
    WeakPreference,
    CandidateObservation,
    RejectedApproach,
    OpenUncertainty,
    GeneratedSummary,
    // These two are present for schema awareness but MUST be rejected by the validator.
    HardRule,
    ProjectInvariant,
}

impl ClaimType {
    /// True if this claim type can originate from LLM output.
    #[must_use]
    pub const fn allowed_from_llm(self) -> bool {
        !matches!(self, Self::HardRule | Self::ProjectInvariant)
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ClaimConfidence {
    Candidate,
    SchemaValidated,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn hard_rule_not_allowed_from_llm() {
        assert!(!ClaimType::HardRule.allowed_from_llm());
        assert!(!ClaimType::ProjectInvariant.allowed_from_llm());
    }

    #[test]
    fn workflow_instruction_allowed() {
        assert!(ClaimType::WorkflowInstruction.allowed_from_llm());
        assert!(ClaimType::CandidateObservation.allowed_from_llm());
    }
}