Normalize constructor review members without losing local history
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use super::catalog::{capture_observation, collection, is_constructor, replace_observation, sides};
|
||||
use super::historical::keyed_slots_overlap;
|
||||
use super::historical::{keyed_slots_overlap, selector_slots};
|
||||
use super::mutate::*;
|
||||
use super::*;
|
||||
use crate::model::*;
|
||||
@@ -297,16 +297,22 @@ fn apply_canonical_slot(
|
||||
let fact = replace_observation(fact, Layer::Sa, desired.clone())?;
|
||||
write_fact(project, owner, &fact, Layer::Sa, Layer::Sa, false)
|
||||
}
|
||||
fn target_only(selector: &FacetSelector, source: Layer, target: Layer) -> bool {
|
||||
match selector {
|
||||
FacetSelector::Member { keys, .. } | FacetSelector::Binding(keys) => {
|
||||
chosen(keys, source).is_none() && chosen(keys, target).is_some()
|
||||
fn member_present(fact: &FacetReview, layer: Layer) -> bool {
|
||||
fn observed<T>(review: &Reviewed<T>, layer: Layer) -> &Observed<T> {
|
||||
match layer {
|
||||
Layer::Oa => &review.oa,
|
||||
Layer::Sa => &review.sa,
|
||||
}
|
||||
FacetSelector::Literal(keys) => {
|
||||
chosen(keys, source).is_none() && chosen(keys, target).is_some()
|
||||
}
|
||||
match fact {
|
||||
FacetReview::Member { review, .. } | FacetReview::Literal { review, .. } => {
|
||||
matches!(observed(review, layer), Observed::Value(true))
|
||||
}
|
||||
FacetSelector::Annotation(keys) => {
|
||||
chosen(keys, source).is_none() && chosen(keys, target).is_some()
|
||||
FacetReview::Annotation { review, .. } => {
|
||||
matches!(observed(review, layer), Observed::Value(Some(_)))
|
||||
}
|
||||
FacetReview::Binding { review, .. } => {
|
||||
matches!(observed(review, layer), Observed::Value(Some(_)))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
@@ -320,15 +326,19 @@ fn preserve_constructor_members(
|
||||
source_layer: Layer,
|
||||
target_layer: Layer,
|
||||
) -> Result<(), String> {
|
||||
// A correspondence key can exist without membership on that side (for
|
||||
// example an OA literal automatically projects the same SA literal key).
|
||||
// Preserve actual target-only values, except previously reviewed removals.
|
||||
for fact in initial_facts {
|
||||
if !constructor_contains(group, &fact.selector)
|
||||
|| !target_only(&fact.selector, source_layer, target_layer)
|
||||
|| member_present(&fact.current, source_layer)
|
||||
|| !member_present(&fact.current, target_layer)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let slot = target_slot(target, &fact.selector, target_layer)?;
|
||||
let was_corresponding = baseline.facets.iter().any(|old| {
|
||||
!target_only(&old.selector(), source_layer, target_layer)
|
||||
member_present(old, source_layer)
|
||||
&& target_slot(target, &old.selector(), target_layer).ok() == Some(slot.clone())
|
||||
});
|
||||
if was_corresponding {
|
||||
@@ -723,12 +733,28 @@ fn build_review(
|
||||
constructor_actions.push((target, selected.clone(), local_record));
|
||||
}
|
||||
let refreshed = semantic_facets(observed, &trace, &references)?;
|
||||
let group_selectors: BTreeSet<_> = refreshed
|
||||
let mut group_selectors: BTreeSet<_> = refreshed
|
||||
.iter()
|
||||
.chain(all.iter())
|
||||
.map(|f| f.selector.clone())
|
||||
.filter(|f| constructor_contains(selected, f))
|
||||
.collect();
|
||||
// A constructor copy can turn a live one-sided member into a
|
||||
// pair. Its initial projection is not another reviewed fact.
|
||||
// Established one-sided history still requires an explicit reset.
|
||||
let paired_sides: BTreeSet<_> = group_selectors
|
||||
.iter()
|
||||
.map(selector_slots)
|
||||
.filter(|slots| slots.len() == 2)
|
||||
.flatten()
|
||||
.collect();
|
||||
group_selectors.retain(|selector| {
|
||||
!paired_sides.contains(selector)
|
||||
|| baseline
|
||||
.facets
|
||||
.iter()
|
||||
.any(|old| old.selector() == *selector)
|
||||
});
|
||||
let mut group = vec![];
|
||||
for selector in group_selectors {
|
||||
match capture_facet(observed, oa, sa, &selector) {
|
||||
|
||||
Reference in New Issue
Block a user