From 8794debdf7777349e27cf11127c959d940fc5451 Mon Sep 17 00:00:00 2001 From: Weksa Date: Fri, 13 Nov 2026 17:23:58 +0000 Subject: [PATCH] Pin the speaker's forms by language and empty list; give ELIDED its doc back Co-Authored-By: Claude Sonnet 5.5 --- crates/weksa/src/context.rs | 2 +- crates/weksa/tests/context.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/crates/weksa/src/context.rs b/crates/weksa/src/context.rs index cad1ff9..0ecd067 100644 --- a/crates/weksa/src/context.rs +++ b/crates/weksa/src/context.rs @@ -538,7 +538,6 @@ struct Meaning<'a> { stance: &'a Stance, } -/// Printed in place of a prior turn whose text no live Train item holds. /// What the lowering prompt prints in place of the item's speaker's entity id: /// one constant, the same for every speaker and every item, so no id and /// nothing derived from one reaches the lowerer. It parses as an entity id so @@ -546,6 +545,7 @@ struct Meaning<'a> { /// ([`LowerError::SpeakerTokenTaken`]); the entity store does not reserve it. pub const SPEAKER_TOKEN: &str = "entity:speaker"; +/// Printed in place of a prior turn whose text no live Train item holds. const ELIDED: &str = "[elided]"; impl Prompt { diff --git a/crates/weksa/tests/context.rs b/crates/weksa/tests/context.rs index e3d8c1b..d2550de 100644 --- a/crates/weksa/tests/context.rs +++ b/crates/weksa/tests/context.rs @@ -839,6 +839,33 @@ mod lowering { } } + /// The speaker's forms are those of the item's language, and a language whose form list is + /// an empty list is no form: the line has no token entry. + #[test] + fn the_speakers_forms_are_those_of_the_items_language() { + let cast = InventoryStore::open(&data("interlingua/inventory.cc")).unwrap(); + let cast_entities = EntityStore::open(&data("entity/entity.cc")).unwrap(); + let view = admitted(proof_packet(), &cast, "corpus/corpus.cc", &cast_entities); + let inv = cast.inventory().unwrap(); + let item = CorpusItemId::parse("item:nibu:1").unwrap(); + let speaker = EntityId::parse("entity:nibu").unwrap(); + let lower = |tag: &str, held: &Held| { + Prompt::lower(&view, &item, &speaker, tag, &inv, held, &weksa::Ontology::empty()) + .unwrap() + .text() + .to_string() + }; + let held = Held(vec![nibu(&[("en-US", &["ENGLISHFORM"]), ("ja-JP", &["NIHONGOFORM"])])]); + let ja = lower("ja-JP", &held); + assert!(ja.contains("\n\nentities: {\"entity:speaker\":[\"NIHONGOFORM\"]}\n\n"), "{ja}"); + assert!(!ja.contains("ENGLISHFORM"), "{ja}"); + let en = lower("en-US", &held); + assert!(en.contains("{\"entity:speaker\":[\"ENGLISHFORM\"]}") && !en.contains("NIHONGOFORM"), "{en}"); + let empty = lower("en-US", &Held(vec![nibu(&[("en-US", &[])])])); + assert!(empty.contains("\n\nentities: {}\n\n") && !empty.contains("entity:speaker"), "{empty}"); + assert!(empty.contains(r#""concept":"concept:5","entity":null"#), "{empty}"); + } + /// A real entity whose id is the token would read as the speaker: refused. #[test] fn a_cited_entity_with_the_tokens_id_is_refused() {