Fix all Clippy warnings across the server codebase (2411 insertions, 1341 deletions). Raise type-complexity-threshold to 750 and too-many-arguments to 12 in .clippy.toml for idiomatic Bevy ECS system signatures. The server now passes `cargo clippy -- --deny warnings` cleanly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
93 lines
3.2 KiB
Rust
93 lines
3.2 KiB
Rust
//! Knowledge grant types for dialogue and monologue lines.
|
|
//!
|
|
//! `KnowledgeGrant` describes the knowledge a player gains from a dialogue line.
|
|
//! `Prerequisites` describes preconditions for a monologue line to fire.
|
|
|
|
use serde::Deserialize;
|
|
use std::collections::BTreeMap;
|
|
|
|
/// Knowledge grant attached to a dialogue line (D-079).
|
|
///
|
|
/// Untagged enum — serde tries each variant in order:
|
|
/// `Fact` matches YAML with `fact_id` field.
|
|
/// `Entity` matches YAML with `entity_ref` field.
|
|
///
|
|
/// **Ambiguity hazard**: if a YAML object contains both `fact_id` and `entity_ref`,
|
|
/// serde(untagged) silently selects `Fact` (first variant wins) and ignores `entity_ref`.
|
|
/// Use [`KnowledgeGrant::validate`] at load time to catch this case.
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
#[serde(untagged)]
|
|
pub enum KnowledgeGrant {
|
|
/// Grant knowledge of a non-entity fact.
|
|
/// Format: fact_id "category.topic", confidence string.
|
|
Fact { fact_id: String, confidence: String },
|
|
/// Grant knowledge of an entity (creates EntityKnowledge entry in observer's KG).
|
|
/// Required for contradiction detection: testimony must create ToldBy EntityKnowledge
|
|
/// so a subsequent DirectObservation can detect a discrepancy (D-079, D-083).
|
|
Entity {
|
|
entity_ref: String,
|
|
#[serde(default)]
|
|
attributes: BTreeMap<String, String>,
|
|
confidence: String,
|
|
},
|
|
}
|
|
|
|
impl KnowledgeGrant {
|
|
/// Validates that the grant is internally consistent.
|
|
///
|
|
/// Specifically catches the serde(untagged) ambiguity: a raw YAML value that has
|
|
/// both `fact_id` and `entity_ref` would parse silently as `Fact`, losing the
|
|
/// entity reference. This can only be detected after deserializing the surrounding
|
|
/// structure — call this on every grant after loading.
|
|
///
|
|
/// Currently there is no post-deserialization raw-value access, so this serves as
|
|
/// a place to add future cross-field validation. Returns `Ok(())` for now.
|
|
pub fn validate(&self) -> Result<(), String> {
|
|
match self {
|
|
KnowledgeGrant::Fact { fact_id, .. } => {
|
|
if fact_id.is_empty() {
|
|
return Err("KnowledgeGrant::Fact has empty fact_id".to_string());
|
|
}
|
|
}
|
|
KnowledgeGrant::Entity { entity_ref, .. } => {
|
|
if entity_ref.is_empty() {
|
|
return Err("KnowledgeGrant::Entity has empty entity_ref".to_string());
|
|
}
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// Prerequisite set for a monologue line.
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
pub struct Prerequisites {
|
|
#[serde(default)]
|
|
pub facts: Vec<FactPrerequisite>,
|
|
#[serde(default)]
|
|
pub entity_attributes: Vec<AttributePrerequisite>,
|
|
#[serde(default)]
|
|
pub relationship: Option<RelationshipPrerequisite>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
pub struct FactPrerequisite {
|
|
pub fact_id: String,
|
|
pub min_confidence: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
pub struct AttributePrerequisite {
|
|
pub entity: String,
|
|
pub key: String,
|
|
pub value: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize)]
|
|
pub struct RelationshipPrerequisite {
|
|
#[serde(default)]
|
|
pub target: Option<String>,
|
|
#[serde(default)]
|
|
pub state: Option<String>,
|
|
}
|