@@ -2187,9 +2187,15 @@ fn apply_once(
21872187 )
21882188 })?;
21892189 let compartment_end = store.max_compartment_end_ordinal(&req.session_id)?;
2190- if compartment_end <= 0 || compartment_end as u64 != expected_boundary {
2190+ // The continuation base is a frozen fact about the descent seam, so it is
2191+ // validated directionally: coverage must have REACHED the seam. Coverage
2192+ // past the seam is the historian folding during the successor run and is
2193+ // legitimate; requiring equality here wedged every continued lineage on
2194+ // its first post-descent fold while the peer's basis stayed correctly
2195+ // frozen at the seam.
2196+ if compartment_end <= 0 || (compartment_end as u64) < expected_boundary {
21912197 return Err(TransformError::LineageProtocol(format!(
2192- "continued lineage requires boundary ordinal {expected_boundary}, found compartment end {compartment_end}; refusing silent re-base-to-1 fallback"
2198+ "continued lineage requires boundary coverage through ordinal {expected_boundary}, found compartment end {compartment_end}; refusing silent re-base-to-1 fallback"
21932199 )));
21942200 }
21952201 let first_live = req
@@ -23541,6 +23547,63 @@ pub(crate) mod tests {
2354123547 assert!(store.load("resolved-target").unwrap().row_version.is_none());
2354223548 }
2354323549
23550+ #[test]
23551+ fn continued_lineage_survives_post_descent_folds_advancing_past_the_seam() {
23552+ // Prod wedge f6a4ca71 (2026-08-11): the continuation base is frozen at
23553+ // the descent seam, but the successor's historian keeps folding. The
23554+ // old equality check fenced every pass after the first successor fold
23555+ // (+2 / +5 compartment-end overhangs); coverage PAST the seam must be
23556+ // accepted, coverage SHORT of it must still refuse.
23557+ let dir = tempfile::tempdir().unwrap();
23558+ let store = store(dir.path());
23559+ seed_fake_compaction_prior(&store, "A");
23560+ let summary = continuation_summary("seam");
23561+ let descent = fake_compaction_request(
23562+ "B",
23563+ "A",
23564+ 2,
23565+ 501,
23566+ true,
23567+ fake_compaction_messages("2026-08-06", &summary),
23568+ );
23569+ let first = run(&store, &descent, &spine());
23570+ assert_eq!(first.lineage_descent_disposition.as_deref(), Some("descended"));
23571+ assert_eq!(first.ordinal_continuation_base, Some(10));
23572+
23573+ // The successor runs on: the historian folds messages past the seam,
23574+ // exactly what a healthy long-lived successor does.
23575+ store
23576+ .append_compartments("B", &[comp(4, 12, 14, "successor-14", "successor work")])
23577+ .unwrap();
23578+
23579+ // An ordinary follow-up pass (no lineage switch) must NOT fence on the
23580+ // advanced compartment end.
23581+ // The successor's wire continues the predecessor's numbering: first
23582+ // live ordinal is base + 1, exactly as the gateway's edge counter
23583+ // assigns it.
23584+ let mut follow_up_messages = vec![
23585+ wire_item(
23586+ "user",
23587+ "summary",
23588+ 11,
23589+ &[
23590+ "<system-reminder>Today's date: 2026-08-06</system-reminder>",
23591+ &summary,
23592+ ],
23593+ ),
23594+ wire_item("assistant", "tail", 12, &["continued answer"]),
23595+ ];
23596+ follow_up_messages.push(item("succ-13", 13, "successor turn thirteen"));
23597+ follow_up_messages.push(item("succ-14", 14, "successor turn fourteen"));
23598+ let follow_up = req("B", "descent-cfg", follow_up_messages);
23599+ let outcome = transform(&store, &follow_up, &pctx("git:proj", "/nonexistent-docs", 0));
23600+ assert!(
23601+ outcome.is_ok(),
23602+ "post-descent fold past the seam must not fence: {:?}",
23603+ outcome.err()
23604+ );
23605+ }
23606+
2354423607 #[test]
2354523608 fn continued_lineage_missing_boundary_aborts_instead_of_rebasing_to_one() {
2354623609 let dir = tempfile::tempdir().unwrap();
0 commit comments