huginn-mind: ran, voted and urged index the runs and pulses a reader asks for newest-first
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
c57cc985d1
commit
6e91f1bf6a
2 changed files with 62 additions and 5 deletions
|
|
@ -1451,6 +1451,39 @@ mod tests {
|
|||
assert!(matches!(mind.query(&other_kind), Err(MindRefusal::SelectionInvalid { .. })));
|
||||
}
|
||||
|
||||
/// `ran` leaves a withdrawn run out and keeps open and recorded ones; `voted`
|
||||
/// and `urged` select the pulses that carry each field.
|
||||
#[test]
|
||||
fn the_ran_voted_and_urged_aliases_are_presence_indexes() {
|
||||
let mut mind = seeded();
|
||||
committed(admit(&mut mind, vec![run("kept", &[]), run("open", &[]), run("unrun", &[])]));
|
||||
let id = |label: &str| r(K::Run, &format!("{INSTANCE}:run:{label}"));
|
||||
committed(admit(&mut mind, vec![resolution(id("kept"), ResolutionOutcome::Recorded { reason: "done".into() })]));
|
||||
committed(admit(&mut mind, vec![resolution(id("unrun"), withdrawn())]));
|
||||
let ran = ids(&mind.query(&with(of_kinds(&[K::Run]), any_of("ran", &["true"]))).unwrap());
|
||||
let run_id = |label: &str| format!("{INSTANCE}:run:{label}");
|
||||
assert_eq!(ran, vec![run_id("kept"), run_id("open")]);
|
||||
let pulse = |label: &str, beat: Option<u32>, urgency: Option<u16>| {
|
||||
D::Pulse(eureka_pipeline::PipelinePulse {
|
||||
instance: Slug(INSTANCE.into()),
|
||||
label: Label(label.into()),
|
||||
tempo_vote_beat_s: beat,
|
||||
urgency_permille: urgency,
|
||||
note: "n".into(),
|
||||
})
|
||||
};
|
||||
committed(admit(&mut mind, vec![pulse("both", Some(60), Some(1)), pulse("vote", Some(60), None), pulse("urge", None, Some(1)), pulse("none", None, None)]));
|
||||
let asking = |alias: &str| {
|
||||
let selection = Selection { descending: true, limit: Some(1), ..with(of_kinds(&[K::Pulse]), any_of(alias, &["true"])) };
|
||||
ids(&mind.query(&selection).unwrap())
|
||||
};
|
||||
let pulse_id = |label: &str| format!("{INSTANCE}:pulse:{label}");
|
||||
assert_eq!(asking("voted"), vec![pulse_id("vote")]);
|
||||
assert_eq!(asking("urged"), vec![pulse_id("urge")]);
|
||||
let outside = with(of_kinds(&[K::Pulse]), any_of("voted", &["false"]));
|
||||
assert!(invalid("fields[0].values", "false")(&refused(&mind, &outside)));
|
||||
}
|
||||
|
||||
/// The substrate's own refusals cross as themselves: an undeclared alias
|
||||
/// is a `SelectionInvalid` from the substrate's door, before the organ's.
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -44,14 +44,24 @@ pub(crate) enum Alias {
|
|||
Turn,
|
||||
/// A run's `operated_by`, read from its fields.
|
||||
OperatedBy,
|
||||
/// `true` on a run that was not withdrawn: it opened and was not unmade
|
||||
/// unrun, so a reader of her last real turn skips the withdrawn ones in the
|
||||
/// index instead of walking past them.
|
||||
Ran,
|
||||
/// `true` on a pulse that casts a tempo vote.
|
||||
Voted,
|
||||
/// `true` on a pulse that declares an urgency.
|
||||
Urged,
|
||||
}
|
||||
|
||||
const FACULTIES: [&str; 7] = ["SelfFaculty", "Imagination", "Hands", "Soul", "Life", "Eyes", "Operator"];
|
||||
const OUTCOMES: [&str; 6] = ["Superseded", "Answered", "Fixed", "Deferred", "Recorded", "Withdrawn"];
|
||||
const BOOLEANS: [&str; 2] = ["true", "false"];
|
||||
/// The one value a presence alias answers with; a row without it answers nothing.
|
||||
const PRESENT: [&str; 1] = ["true"];
|
||||
|
||||
impl Alias {
|
||||
const ALL: [Alias; 13] = [
|
||||
const ALL: [Alias; 16] = [
|
||||
Self::Root,
|
||||
Self::InForce,
|
||||
Self::Faculty,
|
||||
|
|
@ -65,6 +75,9 @@ impl Alias {
|
|||
Self::Outcome,
|
||||
Self::Turn,
|
||||
Self::OperatedBy,
|
||||
Self::Ran,
|
||||
Self::Voted,
|
||||
Self::Urged,
|
||||
];
|
||||
|
||||
fn name(self) -> &'static str {
|
||||
|
|
@ -82,6 +95,9 @@ impl Alias {
|
|||
Self::Outcome => "outcome",
|
||||
Self::Turn => "turn",
|
||||
Self::OperatedBy => "operated_by",
|
||||
Self::Ran => "ran",
|
||||
Self::Voted => "voted",
|
||||
Self::Urged => "urged",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +117,8 @@ impl Alias {
|
|||
Self::Authority => kind == K::Ruling,
|
||||
Self::ClaimOutcome => kind == K::Verdict,
|
||||
Self::Outcome => kind == K::Resolution,
|
||||
Self::Turn | Self::OperatedBy => kind == K::Run,
|
||||
Self::Turn | Self::OperatedBy | Self::Ran => kind == K::Run,
|
||||
Self::Voted | Self::Urged => kind == K::Pulse,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -118,6 +135,7 @@ impl Alias {
|
|||
Self::Outcome => Some(&OUTCOMES),
|
||||
Self::Turn => Some(RunTurn::NAMES),
|
||||
Self::OperatedBy => Some(RunOperator::NAMES),
|
||||
Self::Ran | Self::Voted | Self::Urged => Some(&PRESENT),
|
||||
Self::Root | Self::Repo | Self::Cut => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -222,6 +240,12 @@ impl SelectionRow {
|
|||
D::Run(run) => {
|
||||
put(Alias::Turn, vec![format!("{:?}", run.turn)]);
|
||||
put(Alias::OperatedBy, vec![format!("{:?}", run.operated_by)]);
|
||||
let withdrawn = matches!(&view.status, crate::query::PipelineStatus::Resolved { record, .. } if matches!(record.outcome, ResolutionOutcome::Withdrawn { .. }));
|
||||
put(Alias::Ran, if withdrawn { Vec::new() } else { vec!["true".into()] });
|
||||
}
|
||||
D::Pulse(pulse) => {
|
||||
put(Alias::Voted, if pulse.tempo_vote_beat_s.is_some() { vec!["true".into()] } else { Vec::new() });
|
||||
put(Alias::Urged, if pulse.urgency_permille.is_some() { vec!["true".into()] } else { Vec::new() });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -255,7 +279,7 @@ impl Row for SelectionRow {
|
|||
}
|
||||
}
|
||||
|
||||
/// The organ's closed lists: fifteen schemas, eleven aliases, sixteen roles.
|
||||
/// The organ's closed lists: fifteen schemas, sixteen aliases, sixteen roles.
|
||||
/// A schema's name is its id, so the substrate's alias matching resolves
|
||||
/// nothing beyond exact ids.
|
||||
pub(crate) struct Vocabulary;
|
||||
|
|
@ -382,8 +406,8 @@ mod tests {
|
|||
(K::Instance, &[]),
|
||||
(K::Stewardship, &["repo"]),
|
||||
(K::HandOff, &["repo"]),
|
||||
(K::Run, &["turn", "operated_by"]),
|
||||
(K::Pulse, &[]),
|
||||
(K::Run, &["turn", "operated_by", "ran"]),
|
||||
(K::Pulse, &["voted", "urged"]),
|
||||
];
|
||||
for (kind, extra) in table {
|
||||
let want = [&["root", "in_force", "faculty"][..], extra].concat();
|
||||
|
|
|
|||
Loading…
Reference in a new issue