Follow fission lineage when resuming foundations
This commit is contained in:
parent
36bcc842cf
commit
92d6742546
1 changed files with 129 additions and 7 deletions
|
|
@ -847,6 +847,7 @@ fn rehydrate_complexity_failure(
|
|||
}
|
||||
|
||||
fn civic_manifest_preserves(
|
||||
campaign: &ghostlight_dungeon::domain::Campaign,
|
||||
current: &ghostlight_dungeon::domain::CivicSystemManifest,
|
||||
checkpoint: &ghostlight_dungeon::domain::CivicSystemManifest,
|
||||
) -> bool {
|
||||
|
|
@ -856,9 +857,16 @@ fn civic_manifest_preserves(
|
|||
&& current
|
||||
.governing_institution_ids
|
||||
.is_superset(&checkpoint.governing_institution_ids)
|
||||
&& current
|
||||
&& checkpoint
|
||||
.resident_population_ids
|
||||
.is_superset(&checkpoint.resident_population_ids)
|
||||
.iter()
|
||||
.all(|resident_id| {
|
||||
fission_population_binding_is_present(
|
||||
campaign,
|
||||
¤t.resident_population_ids,
|
||||
resident_id,
|
||||
)
|
||||
})
|
||||
&& current
|
||||
.public_authority_fact_ids
|
||||
.is_superset(&checkpoint.public_authority_fact_ids)
|
||||
|
|
@ -871,12 +879,82 @@ fn civic_manifest_preserves(
|
|||
&& current
|
||||
.public_redress_fact_ids
|
||||
.is_superset(&checkpoint.public_redress_fact_ids)
|
||||
&& current
|
||||
.political_relation_ids
|
||||
.is_superset(&checkpoint.political_relation_ids)
|
||||
&& checkpoint.political_relation_ids.iter().all(|relation_id| {
|
||||
fission_relation_binding_is_present(
|
||||
campaign,
|
||||
¤t.political_relation_ids,
|
||||
relation_id,
|
||||
)
|
||||
})
|
||||
&& !current.semantic_verification_receipt_id.is_empty()
|
||||
}
|
||||
|
||||
fn fission_population_binding_is_present(
|
||||
campaign: &ghostlight_dungeon::domain::Campaign,
|
||||
current_ids: &BTreeSet<String>,
|
||||
expected_id: &str,
|
||||
) -> bool {
|
||||
fn visit(
|
||||
campaign: &ghostlight_dungeon::domain::Campaign,
|
||||
current_ids: &BTreeSet<String>,
|
||||
expected_id: &str,
|
||||
visited: &mut BTreeSet<String>,
|
||||
) -> bool {
|
||||
if current_ids.contains(expected_id) {
|
||||
return true;
|
||||
}
|
||||
if !visited.insert(expected_id.to_owned()) {
|
||||
return false;
|
||||
}
|
||||
campaign
|
||||
.gestalt_lineages
|
||||
.get(expected_id)
|
||||
.is_some_and(|lineage| {
|
||||
!lineage.child_gestalt_ids.is_empty()
|
||||
&& lineage
|
||||
.child_gestalt_ids
|
||||
.iter()
|
||||
.all(|child_id| visit(campaign, current_ids, child_id, visited))
|
||||
})
|
||||
}
|
||||
visit(campaign, current_ids, expected_id, &mut BTreeSet::new())
|
||||
}
|
||||
|
||||
fn fission_relation_binding_is_present(
|
||||
campaign: &ghostlight_dungeon::domain::Campaign,
|
||||
current_ids: &BTreeSet<String>,
|
||||
expected_id: &str,
|
||||
) -> bool {
|
||||
fn visit(
|
||||
campaign: &ghostlight_dungeon::domain::Campaign,
|
||||
current_ids: &BTreeSet<String>,
|
||||
expected_id: &str,
|
||||
used_lineages: &BTreeSet<String>,
|
||||
) -> bool {
|
||||
if current_ids.contains(expected_id) {
|
||||
return true;
|
||||
}
|
||||
campaign.gestalt_lineages.values().any(|lineage| {
|
||||
if used_lineages.contains(&lineage.parent_gestalt_id)
|
||||
|| lineage.child_gestalt_ids.is_empty()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
let mut next_used = used_lineages.clone();
|
||||
next_used.insert(lineage.parent_gestalt_id.clone());
|
||||
lineage.child_gestalt_ids.iter().all(|child_id| {
|
||||
visit(
|
||||
campaign,
|
||||
current_ids,
|
||||
&format!("{expected_id}:fission:{child_id}"),
|
||||
&next_used,
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
visit(campaign, current_ids, expected_id, &BTreeSet::new())
|
||||
}
|
||||
|
||||
fn civic_manifest_is_committed_candidate(
|
||||
current: &ghostlight_dungeon::domain::CivicSystemManifest,
|
||||
candidate: &ghostlight_dungeon::domain::CivicSystemManifest,
|
||||
|
|
@ -1664,7 +1742,9 @@ async fn main() -> anyhow::Result<()> {
|
|||
|| campaign
|
||||
.civic_systems
|
||||
.get(location_id)
|
||||
.is_none_or(|current| !civic_manifest_preserves(current, &expected_civic))
|
||||
.is_none_or(|current| {
|
||||
!civic_manifest_preserves(&campaign, current, &expected_civic)
|
||||
})
|
||||
{
|
||||
anyhow::bail!(
|
||||
"foundation checkpoint for {location_id} is not committed in the resumed campaign"
|
||||
|
|
@ -3756,6 +3836,7 @@ mod tests {
|
|||
HistoricalWorldNewspaperGroundingVerdict, HistoricalWorldNewspaperIssueV2,
|
||||
admitted_public_channel, civic_manifest_is_committed_candidate,
|
||||
committed_elaboration_mutation_proof, completed_wave_issue_campaign, final_wave_field,
|
||||
fission_population_binding_is_present, fission_relation_binding_is_present,
|
||||
latest_partial_wave_checkpoint, missing_newspaper_report_indices,
|
||||
publish_immutable_checkpoint, recomposed_model_receipt_set_digest,
|
||||
recover_committed_clock_binding, strategic_campaign, strategic_locality_request,
|
||||
|
|
@ -3784,6 +3865,47 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resumed_foundation_bindings_follow_complete_fission_lineage() {
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
let mut campaign = strategic_campaign();
|
||||
campaign.gestalt_lineages.insert(
|
||||
"residents".into(),
|
||||
ghostlight_dungeon::domain::GestaltLineage {
|
||||
schema: "ghostlight.gestalt_lineage.v1".into(),
|
||||
parent_gestalt_id: "residents".into(),
|
||||
child_gestalt_ids: vec!["east".into(), "west".into()],
|
||||
partition_axis: ghostlight_dungeon::domain::AgencyAxis::Geography,
|
||||
partition_values: BTreeMap::from([
|
||||
("east".into(), "east".into()),
|
||||
("west".into(), "west".into()),
|
||||
]),
|
||||
residual_child_id: "west".into(),
|
||||
source_revision: 1,
|
||||
},
|
||||
);
|
||||
let residents = BTreeSet::from(["east".into(), "west".into()]);
|
||||
let relations = BTreeSet::from([
|
||||
"relation:fission:east".into(),
|
||||
"relation:fission:west".into(),
|
||||
]);
|
||||
|
||||
assert!(fission_population_binding_is_present(
|
||||
&campaign,
|
||||
&residents,
|
||||
"residents"
|
||||
));
|
||||
assert!(fission_relation_binding_is_present(
|
||||
&campaign, &relations, "relation"
|
||||
));
|
||||
assert!(!fission_relation_binding_is_present(
|
||||
&campaign,
|
||||
&BTreeSet::from(["relation:fission:east".into()]),
|
||||
"relation"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn top_level_projection_uses_the_final_wave_head() {
|
||||
let waves = vec![
|
||||
|
|
@ -4559,4 +4681,4 @@ mod tests {
|
|||
);
|
||||
}
|
||||
}
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
|
|
|||
Loading…
Reference in a new issue