RulingAuthority gains Mind: a ruling the Mind's Self makes is its own word
Additive unit-enum variant; schemas regenerated by derivation. The query alias domain now derives from the enum (unit_enums! exposes NAMES), so the second authority list in huginn-mind rows.rs is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
afc35f92d1
commit
775148f28b
7 changed files with 74 additions and 7 deletions
|
|
@ -439,6 +439,11 @@ macro_rules! unit_enums {
|
|||
($($name:ident { $($variant:ident),* $(,)? })*) => {$(
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
pub enum $name { $($variant),* }
|
||||
impl $name {
|
||||
/// The variants' spellings, in declaration order: the names the wire and
|
||||
/// `Debug` use.
|
||||
pub const NAMES: &'static [&'static str] = &[$(stringify!($variant)),*];
|
||||
}
|
||||
impl Bounded for $name {
|
||||
fn validate(&self, _field: &str) -> Result<(), PipelineRefusal> {
|
||||
Ok(())
|
||||
|
|
@ -472,7 +477,7 @@ unit_enums! {
|
|||
ClaimOutcome { Holds, Falsified, Unproven }
|
||||
FindingConfidence { Confirmed, Plausible }
|
||||
FindingSeverity { Blocker, High, Medium, Low }
|
||||
RulingAuthority { Operator, Standing, Defaulted }
|
||||
RulingAuthority { Operator, Standing, Defaulted, Mind }
|
||||
FindingOrigin { Introduced, PreExisting }
|
||||
}
|
||||
|
||||
|
|
@ -1269,6 +1274,39 @@ mod tests {
|
|||
ruling
|
||||
}
|
||||
|
||||
/// A ruling the Mind's own Self made: authority Mind, no operator quote,
|
||||
/// no question answered. Built from the ruling sample, not inserted into
|
||||
/// `samples()`, whose tests pick kinds by index.
|
||||
fn mind_ruling() -> PipelineRuling {
|
||||
let mut ruling = ruling_sample();
|
||||
(ruling.authority, ruling.operator_quote, ruling.answers, ruling.choice) = (RulingAuthority::Mind, None, None, None);
|
||||
ruling
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_ruling_with_authority_mind_keys_encodes_and_round_trips_like_any_ruling() -> Result<()> {
|
||||
let cache = schema_cache()?;
|
||||
let document = PipelineDocument::Ruling(mind_ruling());
|
||||
document.validate()?;
|
||||
let envelope = document.prepare(&cache)?;
|
||||
assert!(envelope.key.starts_with("eureka-state:ruling:"), "{}", envelope.key);
|
||||
assert_eq!(PipelineDocument::decode(&envelope)?, document);
|
||||
let json = serde_json::to_value(&document)?;
|
||||
assert_eq!(json["value"]["authority"], "Mind");
|
||||
assert_eq!(serde_json::from_value::<PipelineDocument>(json)?, document);
|
||||
let packed = rmp_serde::to_vec_named(&document)?;
|
||||
assert_eq!(rmp_serde::from_slice::<PipelineDocument>(&packed)?, document);
|
||||
let standing = PipelineDocument::Ruling(ruling_sample());
|
||||
assert_ne!(standing.prepare(&cache)?.payload, envelope.payload, "Mind is not a spelling of another authority");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unit_enum_names_are_the_variants_in_declaration_order() {
|
||||
assert_eq!(RulingAuthority::NAMES, ["Operator", "Standing", "Defaulted", "Mind"]);
|
||||
assert_eq!(FindingOrigin::NAMES, ["Introduced", "PreExisting"]);
|
||||
}
|
||||
|
||||
fn report_sample() -> PipelineCutReport {
|
||||
let PipelineDocument::CutReport(report) = samples().remove(5).0 else { unreachable!() };
|
||||
report
|
||||
|
|
@ -1340,6 +1378,7 @@ mod tests {
|
|||
f.severity = severity;
|
||||
out.push((format!("finding.severity-{name}"), D::Finding(f)));
|
||||
}
|
||||
out.push(("ruling.authority-mind".into(), D::Ruling(mind_ruling())));
|
||||
out
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1859,10 +1859,21 @@ mod tests {
|
|||
let mut quoted = ruling("R1");
|
||||
quoted.operator_quote = Some("all recommendations, go ahead".into());
|
||||
assert_eq!(refusal(admit(&mut mind, vec![D::Ruling(quoted.clone())])), MindRefusal::QuoteWithoutOperator { ruling: id("ruling", "R1") });
|
||||
quoted.authority = RulingAuthority::Mind;
|
||||
assert_eq!(refusal(admit(&mut mind, vec![D::Ruling(quoted.clone())])), MindRefusal::QuoteWithoutOperator { ruling: id("ruling", "R1") });
|
||||
assert!(mind.get(K::Ruling, &id("ruling", "R1")).unwrap().is_none(), "a refused batch leaves the store unchanged");
|
||||
quoted.authority = RulingAuthority::Operator;
|
||||
committed(admit(&mut mind, vec![D::Ruling(quoted)]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_mind_ruling_without_a_quote_is_admitted() {
|
||||
let mut mind = seeded();
|
||||
let mut own = ruling("R1");
|
||||
own.authority = RulingAuthority::Mind;
|
||||
committed(admit(&mut mind, vec![D::Ruling(own)]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_revision_requires_its_predecessors_supersession_in_the_batch() {
|
||||
let mut mind = seeded();
|
||||
|
|
|
|||
|
|
@ -1219,6 +1219,21 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
/// The alias domain and the enum agree: a Mind-authority ruling is
|
||||
/// selectable by its own word, and only by it.
|
||||
#[test]
|
||||
fn a_query_for_mind_authority_is_answered() {
|
||||
let mut mind = seeded();
|
||||
let mut own = ruling("R1");
|
||||
own.authority = RulingAuthority::Mind;
|
||||
committed(admit(&mut mind, vec![D::Ruling(own), D::Ruling(ruling("R2"))]));
|
||||
let by = |word: &str| mind.query(&with(of_kinds(&[K::Ruling]), any_of("authority", &[word]))).unwrap();
|
||||
assert_eq!(by("Mind").matched, 1);
|
||||
assert_eq!(by("Standing").matched, 1);
|
||||
let misspelt = with(of_kinds(&[K::Ruling]), any_of("authority", &["Minds"]));
|
||||
assert!(matches!(refused(&mind, &misspelt), MindRefusal::SelectionInvalid { value: Some(v), .. } if v == "Minds"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_unknown_schema_or_malformed_key_is_refused() {
|
||||
let mind = worked();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use cultnet_rs::{Row, RowSet, Selection};
|
||||
use eureka_pipeline::{OrgRepo, Label, PipelineDocument, PipelineKind, PipelineRef, ResolutionOutcome, Slug};
|
||||
use eureka_pipeline::{OrgRepo, Label, PipelineDocument, PipelineKind, PipelineRef, ResolutionOutcome, RulingAuthority, Slug};
|
||||
|
||||
use crate::docs::{CitationRole, Held, kind_of_id, kind_of_type};
|
||||
use crate::query::PipelineDocumentView;
|
||||
|
|
@ -43,7 +43,6 @@ const FACULTIES: [&str; 7] = ["SelfFaculty", "Imagination", "Hands", "Soul", "Li
|
|||
const SEVERITIES: [&str; 4] = ["Blocker", "High", "Medium", "Low"];
|
||||
const CONFIDENCES: [&str; 2] = ["Confirmed", "Plausible"];
|
||||
const ORIGINS: [&str; 2] = ["Introduced", "PreExisting"];
|
||||
const AUTHORITIES: [&str; 3] = ["Operator", "Standing", "Defaulted"];
|
||||
const CLAIM_OUTCOMES: [&str; 3] = ["Holds", "Falsified", "Unproven"];
|
||||
const OUTCOMES: [&str; 6] = ["Superseded", "Answered", "Fixed", "Deferred", "Recorded", "Withdrawn"];
|
||||
const BOOLEANS: [&str; 2] = ["true", "false"];
|
||||
|
|
@ -106,7 +105,7 @@ impl Alias {
|
|||
Self::Severity => Some(&SEVERITIES),
|
||||
Self::Confidence => Some(&CONFIDENCES),
|
||||
Self::Origin => Some(&ORIGINS),
|
||||
Self::Authority => Some(&AUTHORITIES),
|
||||
Self::Authority => Some(RulingAuthority::NAMES),
|
||||
Self::ClaimOutcome => Some(&CLAIM_OUTCOMES),
|
||||
Self::Outcome => Some(&OUTCOMES),
|
||||
Self::Root | Self::Repo | Self::Cut => None,
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@
|
|||
"enum": [
|
||||
"Operator",
|
||||
"Standing",
|
||||
"Defaulted"
|
||||
"Defaulted",
|
||||
"Mind"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1674,7 +1674,8 @@
|
|||
"enum": [
|
||||
"Operator",
|
||||
"Standing",
|
||||
"Defaulted"
|
||||
"Defaulted",
|
||||
"Mind"
|
||||
]
|
||||
},
|
||||
"SemanticQuery": {
|
||||
|
|
|
|||
|
|
@ -3702,7 +3702,8 @@
|
|||
"enum": [
|
||||
"Operator",
|
||||
"Standing",
|
||||
"Defaulted"
|
||||
"Defaulted",
|
||||
"Mind"
|
||||
]
|
||||
},
|
||||
"Sha": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue