Complete source 6 engineering workflows and preserve release validation evidence

This commit is contained in:
Codex
2026-09-06 21:49:04 -07:00
parent 2b2d2bc18b
commit 4b6b5fc197
290 changed files with 48271 additions and 1791 deletions
@@ -172,8 +172,8 @@ fn ready(f: &Fixture, reverse: bool) -> State {
state
}
fn decide(state: &mut State, p: &Project, facet: FacetSelector, decision: SemanticDecision) {
state.update(p, Event::Select(facet.clone()));
state.update(p, Event::Decide(facet, Some(decision)));
state.update(p, RowEvent::Select(facet.clone()));
state.update(p, RowEvent::Decide(facet, Some(decision)));
}
fn errors(s: &State) -> String {
s.error
@@ -231,7 +231,7 @@ fn ordered_take_uses_unique_anchors_and_matches_core_with_unrelated_candidate_bo
decide(&mut s, &f.p, header, SemanticDecision::Candidate);
s.update(
&f.p,
Event::Input("/description".into(), "Reviewed startup insertion".into()),
RowEvent::Input("/description".into(), "Reviewed startup insertion".into()),
);
let ti = 1 - usize::from(reverse);
let mut expected = f.p.clone();
@@ -268,7 +268,7 @@ fn ambiguous_order_preserves_local_member_and_requires_explicit_candidate_positi
s.order_drafts[&f.which],
vec![f.rows[ti][0], f.rows[ti][3], f.rows[ti][1], f.rows[ti][2]]
);
s.update(&f.p, Event::OrderMove(f.which, 3, -1));
s.update(&f.p, RowEvent::OrderMove(f.which, 3, -1));
let mut expected = f.p.clone();
set_order(
&mut expected,
@@ -297,7 +297,7 @@ fn ordered_membership_choices_stage_exact_pairs_in_all_owner_shapes() {
let mut s = ready(&f, false);
s.update(
&f.p,
Event::MemberFamily(keyed::Family::Member(ordered::collection(f.which))),
RowEvent::MemberFamily(keyed::Family::Member(ordered::collection(f.which))),
);
for (i, layer) in [(0, Layer::Oa), (1, Layer::Sa)] {
let choices = s.member_choices(&f.p, layer);
@@ -311,13 +311,13 @@ fn ordered_membership_choices_stage_exact_pairs_in_all_owner_shapes() {
}
s.update(
&f.p,
Event::MemberOa(Some(view::choice(&f.p, f.rows[0][2]))),
RowEvent::MemberOa(Some(view::choice(&f.p, f.rows[0][2]))),
);
s.update(
&f.p,
Event::MemberSa(Some(view::choice(&f.p, f.rows[1][2]))),
RowEvent::MemberSa(Some(view::choice(&f.p, f.rows[1][2]))),
);
s.update(&f.p, Event::StageMember);
s.update(&f.p, RowEvent::StageMember);
assert!(s.staged.contains(&member(&f, 2)));
assert_eq!(s.references[&f.rows[0][2]], f.rows[1][2]);
}
@@ -330,20 +330,20 @@ fn raw_order_survives_membership_changes_decisions_and_recovery_until_explicit_r
let mut s = ready(&f, reverse);
let order = FacetSelector::Order(f.which);
decide(&mut s, &f.p, order.clone(), SemanticDecision::Candidate);
s.update(&f.p, Event::OrderMove(f.which, 1, -1));
s.update(&f.p, RowEvent::OrderMove(f.which, 1, -1));
let authored = s.order_drafts[&f.which].clone();
decide(&mut s, &f.p, member(&f, 2), SemanticDecision::Candidate);
s.update(&f.p, Event::Presence(member(&f, 2), true));
s.update(&f.p, RowEvent::Presence(member(&f, 2), true));
assert!(!s.can_apply());
assert_eq!(s.order_drafts[&f.which], authored);
s.update(&f.p, Event::Decide(order.clone(), None));
s.update(&f.p, RowEvent::Decide(order.clone(), None));
decide(&mut s, &f.p, order.clone(), SemanticDecision::Candidate);
let saved = s.recovery_snapshot().unwrap();
let mut restored = State::from_recovery(&f.p, saved.clone()).unwrap();
assert_eq!(restored.order_drafts[&f.which], authored);
assert!(!restored.can_apply());
assert_eq!(restored.recovery_snapshot().unwrap(), saved);
restored.update(&f.p, Event::OrderReconcile(f.which));
restored.update(&f.p, RowEvent::OrderReconcile(f.which));
let ti = 1 - usize::from(reverse);
let mut expected = f.p.clone();
let mut final_order = authored;
@@ -385,7 +385,7 @@ fn order_take_preserves_destination_only_positions_and_order_alone_cannot_add_me
s.refresh(&f.p);
assert!(!s.can_apply());
assert!(errors(&s).contains("surviving"), "{}", errors(&s));
s.update(&f.p, Event::OrderReconcile(f.which));
s.update(&f.p, RowEvent::OrderReconcile(f.which));
assert!(s.can_apply(), "{}", errors(&s));
}
}
@@ -406,28 +406,28 @@ fn ordered_review_apply_is_exact_source_history_transaction_with_reopen_and_undo
for i in 0..3 {
send(
&mut app,
Event::ReferenceOa(view::choice(&f.p, f.rows[0][i])),
RowEvent::ReferenceOa(view::choice(&f.p, f.rows[0][i])),
);
send(
&mut app,
Event::ReferenceSa(view::choice(&f.p, f.rows[1][i])),
RowEvent::ReferenceSa(view::choice(&f.p, f.rows[1][i])),
);
send(&mut app, Event::AddReference);
send(&mut app, RowEvent::AddReference);
}
send(&mut app, Event::Select(member(&f, 2)));
send(&mut app, RowEvent::Select(member(&f, 2)));
send(
&mut app,
Event::Decide(member(&f, 2), Some(SemanticDecision::TakeSource)),
RowEvent::Decide(member(&f, 2), Some(SemanticDecision::TakeSource)),
);
send(&mut app, Event::Select(FacetSelector::Order(f.which)));
send(&mut app, RowEvent::Select(FacetSelector::Order(f.which)));
send(
&mut app,
Event::Decide(
RowEvent::Decide(
FacetSelector::Order(f.which),
Some(SemanticDecision::Candidate),
),
);
send(&mut app, Event::OrderMove(f.which, 3, -1));
send(&mut app, RowEvent::OrderMove(f.which, 3, -1));
assert!(state(&app).can_apply(), "{}", errors(state(&app)));
let expected = state(&app).proposed.clone().unwrap();
apply(&mut app);
@@ -479,7 +479,7 @@ fn several_incoming_members_follow_source_order_despite_independent_identity_sor
);
s.update(
&f.p,
Event::Input("/description".into(), "Multiple incoming steps".into()),
RowEvent::Input("/description".into(), "Multiple incoming steps".into()),
);
let mut expected = f.p.clone();
set_order(
@@ -513,7 +513,7 @@ fn ordered_presence_keep_take_candidate_remove_only_selected_entry_and_order_tak
let mut s = ready(&f, reverse);
decide(&mut s, &f.p, member(&f, 0), decision);
if decision == SemanticDecision::Candidate {
s.update(&f.p, Event::Presence(member(&f, 0), false));
s.update(&f.p, RowEvent::Presence(member(&f, 0), false));
}
decide(
&mut s,
@@ -523,7 +523,7 @@ fn ordered_presence_keep_take_candidate_remove_only_selected_entry_and_order_tak
);
s.update(
&f.p,
Event::Input("/description".into(), "Only selected membership".into()),
RowEvent::Input("/description".into(), "Only selected membership".into()),
);
let mut expected = f.p.clone();
if decision != SemanticDecision::KeepTarget {
@@ -565,3 +565,58 @@ fn ordered_presence_keep_take_candidate_remove_only_selected_entry_and_order_tak
}
}
}
#[test]
fn historical_pair_restore_uses_exact_member_keys_and_never_zips_order_observations() {
let f = fixture(0, false, true);
let mut state = ready(&f, false);
decide(
&mut state,
&f.p,
member(&f, 2),
SemanticDecision::TakeSource,
);
decide(
&mut state,
&f.p,
FacetSelector::Order(f.which),
SemanticDecision::Candidate,
);
state.update(&f.p, RowEvent::OrderMove(f.which, 3, -1));
assert!(state.can_apply(), "{}", errors(&state));
let project = state.proposed.clone().unwrap();
let mut reopened = State::new(&project, f.trace).unwrap();
let exact = history::reviewed_pairs(&reopened, &project).unwrap();
assert_eq!(exact, BTreeMap::from([(f.rows[0][2], f.rows[1][2])]));
assert_eq!(
project.traces[&f.trace]
.baseline
.as_ref()
.unwrap()
.semantic
.as_ref()
.unwrap()
.facets
.len(),
2
);
reopened.update(&project, RowEvent::RestoreReviewedReferences);
assert_eq!(reopened.references, exact);
assert!(reopened.decisions.is_empty());
assert_eq!(reopened.proposed.as_ref(), Some(&project));
reopened.references.insert(f.rows[0][2], f.rows[1][0]);
let prior = reopened.references.clone();
reopened.update(&project, RowEvent::RestoreReviewedReferences);
assert!(reopened.error.as_ref().unwrap().contains("conflicts"));
assert_eq!(
reopened.references, prior,
"Restore is atomic on disagreement"
);
reopened.references.clear();
reopened.update(&project, RowEvent::Reset(member(&f, 2), true));
assert!(
history::reviewed_pairs(&reopened, &project)
.unwrap()
.is_empty()
);
}