reasoninglayer 0.1.2

Rust client SDK for the Reasoning Layer API
Documentation
//! Advanced reasoning DTOs (entailment, residuation, temporal planning, coordination).

use std::collections::BTreeMap;

use serde::{Deserialize, Serialize};

use super::fuzzy::QueryTerm;
use super::homoiconic::TermInputDto;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EntailmentRequest {
    pub antecedent: TermInputDto,
    pub consequent: TermInputDto,
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub facts: Vec<TermInputDto>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EntailmentResponse {
    pub computation_time_ms: u64,
    pub confidence: f64,
    pub entails: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DisentailmentRequest {
    pub antecedent: TermInputDto,
    pub consequent: TermInputDto,
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub facts: Vec<TermInputDto>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DisentailmentResponse {
    pub computation_time_ms: u64,
    pub confidence: f64,
    pub holds: bool,
    pub violated: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EvidenceAssessmentRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub aggregation_strategy: Option<String>,
    pub evidence_link_field: String,
    pub evidence_sort_id: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub penalty_field: Option<String>,
    pub quality_field: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub quality_threshold: Option<f64>,
    pub subject_id: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub subject_penalty_field: Option<String>,
    pub support_field: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EvidenceItemDto {
    pub contribution: f64,
    pub quality_weight: f64,
    pub supports: bool,
    pub term_id: String,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct EvidenceAssessmentResponse {
    pub avg_contradict_quality: f64,
    pub avg_support_quality: f64,
    pub color: String,
    pub computation_time_ms: u64,
    #[serde(default)]
    pub contradicting_evidence: Vec<EvidenceItemDto>,
    pub evidence_count: u64,
    #[serde(default)]
    pub explanation: Vec<String>,
    pub label: String,
    pub max_quality: f64,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub penalty_applied: Option<f64>,
    pub residuated: bool,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub residuation_reason: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub residuation_trigger: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub score_before_penalty: Option<f64>,
    pub subject_id: String,
    #[serde(default)]
    pub supporting_evidence: Vec<EvidenceItemDto>,
    pub truthfulness: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResiduationRequest {
    pub term_id: String,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ResiduationResponse {
    pub computation_time_ms: u64,
    #[serde(default)]
    pub resumption_triggers: Vec<String>,
    #[serde(default)]
    pub suspended_operations: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GoalResiduationRequest {
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub available_sorts: Vec<String>,
    pub goal_sort_name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub max_results: Option<u32>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResiduatedEntryDto {
    pub feature_name: String,
    pub info_gain: f64,
    #[serde(default)]
    pub needed_by: Vec<String>,
    pub rule_count: u64,
    pub wake_trigger: String,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct GoalResiduationResponse {
    pub computation_time_ms: u64,
    #[serde(default)]
    pub entries: Vec<ResiduatedEntryDto>,
    pub rules_analysed: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceSpec {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub fuzzy_query: Option<QueryTerm>,
    pub match_field: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub min_degree: Option<f64>,
    pub sort_id: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceCoordinationRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub compatibility_threshold: Option<f64>,
    pub num_selections: u32,
    pub resources: Vec<ResourceSpec>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CoordinatedResourceSet {
    pub compatibility_score: f64,
    pub resource_ids: Vec<String>,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ResourceCoordinationResponse {
    pub avg_compatibility: f64,
    #[serde(default)]
    pub candidates_per_resource: Vec<u64>,
    pub computation_time_ms: u64,
    #[serde(default)]
    pub coordinated_sets: Vec<CoordinatedResourceSet>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemporalPlanRequest {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub distance_metric: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub fuzzy_query: Option<QueryTerm>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub group_by_field: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub max_distance_km: Option<f64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub min_degree: Option<f64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub no_repeat_fields: Option<Vec<String>>,
    pub num_selections: u32,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub proximity_weight: Option<f64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub sequence_by_field: Option<String>,
    pub sort_id: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub top_k: Option<BTreeMap<String, f64>>,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct TemporalPlanResponse {
    pub candidates_count: u64,
    pub computation_time_ms: u64,
    pub diversity_score: f64,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub proximity_score: Option<f64>,
    #[serde(default)]
    pub selected_term_ids: Vec<String>,
}

// ─── Fuzzy merge / subsumption / residuate (shared with fuzzy but accessed via reasoning path) ─

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FuzzySubsumptionResponseReasoning {
    pub degree: f64,
    pub subsumes: bool,
}