From 5e00a7bbc3f540ef35d18abe89f84687b5004664 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 27 Aug 2026 05:01:57 +0200 Subject: [PATCH] Remove hidden institution posture ceiling --- crates/ghostlight-dungeon/src/kernel.rs | 51 +++++++++++++++++++++ crates/ghostlight-dungeon/src/outcome.rs | 19 ++++++++ crates/ghostlight-dungeon/src/resolution.rs | 30 +++++++----- 3 files changed, 89 insertions(+), 11 deletions(-) diff --git a/crates/ghostlight-dungeon/src/kernel.rs b/crates/ghostlight-dungeon/src/kernel.rs index 01f3fe0..d763176 100644 --- a/crates/ghostlight-dungeon/src/kernel.rs +++ b/crates/ghostlight-dungeon/src/kernel.rs @@ -5818,6 +5818,57 @@ pub(crate) mod tests { ); } + #[test] + fn institution_posture_uses_the_canonical_character_bound_at_commit() { + let mut value = campaign(); + value.institutions.insert( + "board".into(), + InstitutionState { + id: "board".into(), + name: "Board".into(), + resources: vec![], + goals: vec![], + posture: "watching".into(), + }, + ); + crate::resolution::ensure_agency_profiles(&mut value); + apply_strategic_tick_plan( + &mut value, + StrategicTickPlan { + institution_actions: vec![StrategicInstitutionAction { + institution_id: "board".into(), + posture: "x".repeat(MAX_POSTURE_CHARS), + location_ids: vec![], + public_channels: vec![], + }], + ..Default::default() + }, + ) + .unwrap(); + assert_eq!( + value.institutions["board"].posture.chars().count(), + MAX_POSTURE_CHARS + ); + + let before_oversized = value.clone(); + assert!( + apply_strategic_tick_plan( + &mut value, + StrategicTickPlan { + institution_actions: vec![StrategicInstitutionAction { + institution_id: "board".into(), + posture: "y".repeat(MAX_POSTURE_CHARS + 1), + location_ids: vec![], + public_channels: vec![], + }], + ..Default::default() + }, + ) + .is_err() + ); + assert_eq!(value, before_oversized); + } + #[test] fn canonical_action_commits_distinct_scopes_of_one_activity_kind() { let mut value = hierarchical_refugee_campaign(); diff --git a/crates/ghostlight-dungeon/src/outcome.rs b/crates/ghostlight-dungeon/src/outcome.rs index 1333df2..b180a7a 100644 --- a/crates/ghostlight-dungeon/src/outcome.rs +++ b/crates/ghostlight-dungeon/src/outcome.rs @@ -2611,6 +2611,25 @@ mod tests { } } + #[test] + fn member_outcome_text_retains_its_field_specific_bound() { + let mut exact = BTreeSet::new(); + validate_member_owner("member:mira", "mira", &"x".repeat(240), "memory", &mut exact) + .unwrap(); + + let mut oversized = BTreeSet::new(); + assert!( + validate_member_owner( + "member:mira", + "mira", + &"x".repeat(241), + "memory", + &mut oversized, + ) + .is_err() + ); + } + #[test] fn outcome_verifier_schema_makes_result_guidance_coherence_structural() { let digest = format!("sha256:{}", "a".repeat(64)); diff --git a/crates/ghostlight-dungeon/src/resolution.rs b/crates/ghostlight-dungeon/src/resolution.rs index 77ced31..d465f8f 100644 --- a/crates/ghostlight-dungeon/src/resolution.rs +++ b/crates/ghostlight-dungeon/src/resolution.rs @@ -2475,9 +2475,7 @@ fn is_human_controlled_actor(campaign: &Campaign, subject_id: &str) -> bool { pub fn substantive_text_change(current: &str, candidate: &str) -> bool { let current = current.trim(); let candidate = candidate.trim(); - !candidate.is_empty() - && candidate.chars().count() <= 240 - && !current.eq_ignore_ascii_case(candidate) + !candidate.is_empty() && !current.eq_ignore_ascii_case(candidate) } pub fn validate_gestalt_pressure_transition( @@ -4007,16 +4005,9 @@ pub(crate) mod tests { "holding position", "releasing the reserve" )); - let schema_max_with_unicode = format!("{}’", "a".repeat(239)); - assert_eq!(schema_max_with_unicode.chars().count(), 240); - assert!(schema_max_with_unicode.len() > 240); assert!(substantive_text_change( "holding position", - &schema_max_with_unicode - )); - assert!(!substantive_text_change( - "holding position", - &format!("{schema_max_with_unicode}a") + &"a".repeat(MAX_POSTURE_CHARS + 1) )); } @@ -4280,6 +4271,23 @@ pub(crate) mod tests { }]; validate_and_resolve_wave(&value, &mixed).unwrap(); + let mut maximum_posture = valid_action.clone(); + let StrategicCellEffect::Institution { posture, .. } = + &mut maximum_posture.effects[0] + else { + unreachable!() + }; + *posture = "x".repeat(MAX_POSTURE_CHARS); + validate_and_resolve_wave(&value, &make_wave(maximum_posture.clone())).unwrap(); + + let StrategicCellEffect::Institution { posture, .. } = + &mut maximum_posture.effects[0] + else { + unreachable!() + }; + posture.push('x'); + assert!(validate_and_resolve_wave(&value, &make_wave(maximum_posture)).is_err()); + let mut omitted = mixed.clone(); omitted.appraisals[0].inactions.clear(); assert!(