encode prompt: state V11's one-role rule and the group referent that coordinates fillers

Item original-ja:19 is refused V11DuplicateRole in every round because the
encoder prompt never stated the rule. The prompt now says a role holds one
filler, coordinated fillers are one group referent, each member related by
member_of from member to group. Validator and data untouched; the prompt
digest changes by design.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Weksa 2026-11-12 18:45:32 +00:00
commit 6e0a2f4857
3 changed files with 38 additions and 1 deletions

View file

@ -64,7 +64,7 @@ Fields:
- predications: a list of {id, concept, frame, roles, features}; roles is a list of {role, filler}, filler a node id.
- relations: a list of {relation, from, to, features}.
- stance: {features}; the speaker's felt affect and restraint, never the affect the line displays.
Node ids are n1, n2, and so on, one per referent and predication. Every other id comes from the inventory listed below and must be live at its revision. Write each id in full, exactly as the inventory lines spell it, family prefix included: concept:7, never 7. An entity comes only from the entities line. A referent's concept is never null, even when it carries an entity: give the nearest concept id. Participants and audience list the node ids of referents, never an entity id: an entity speaker is a referent whose entity field holds it, and participants lists that referent's node id.
Node ids are n1, n2, and so on, one per referent and predication. Every other id comes from the inventory listed below and must be live at its revision. Write each id in full, exactly as the inventory lines spell it, family prefix included: concept:7, never 7. An entity comes only from the entities line. A referent's concept is never null, even when it carries an entity: give the nearest concept id. Participants and audience list the node ids of referents, never an entity id: an entity speaker is a referent whose entity field holds it, and participants lists that referent's node id. A predication holds each role at most once, and a feature list each feature at most once: two or more fillers of one role are one referent of kind group that fills the role, and each member is related to it by a member_of relation from the member to the group.
A feature is {feature, value}; value is {\"Grade\": 0 to 1000}, {\"Option\": label} or {\"Flag\": true or false}, as the inventory lists the feature's kind.";
/// The instructions a lowering prompt starts with: the lowerer's whole brief.

View file

@ -474,6 +474,39 @@ mod tests {
assert_eq!(PacketDraft::of(&made), draft);
}
#[test]
fn coordinated_fillers_admit_as_one_group_referent() {
use crate::store::InventoryStore;
use crate::validate::{Refusal, validate};
// Item original-ja:19 as measure-ja-2 recorded it: two patients, one role twice.
const REFUSED: &str = r#"{"confidence":720,"context":{"setting":null,"medium":null,"participants":["n1"],"audience":["n1"]},"discourse":{"speech_act":"speech_act:3","addressee":null,"addressee_consent":null,"features":[]},"referents":[{"id":"n1","kind":"referent_kind:1","concept":"concept:28","entity":"entity:keeper","features":[]},{"id":"n2","kind":"referent_kind:1","concept":"concept:31","entity":null,"features":[]},{"id":"n3","kind":"referent_kind:5","concept":"concept:123","entity":null,"features":[]},{"id":"n4","kind":"referent_kind:5","concept":"concept:123","entity":null,"features":[]}],"predications":[{"id":"n5","concept":"concept:26","frame":"frame:4","roles":[{"role":"role:1","filler":"n1"},{"role":"role:2","filler":"n3"},{"role":"role:2","filler":"n4"}],"features":[{"feature":"feature:1","value":{"Option":"positive"}},{"feature":"feature:2","value":{"Option":"present"}},{"feature":"feature:3","value":{"Option":"habitual"}}]},{"id":"n6","concept":"concept:196","frame":"frame:4","roles":[{"role":"role:1","filler":"n1"},{"role":"role:2","filler":"n5"}],"features":[{"feature":"feature:1","value":{"Option":"positive"}},{"feature":"feature:2","value":{"Option":"future"}},{"feature":"feature:4","value":{"Option":"desired"}}]}],"relations":[{"relation":"relation:11","from":"n2","to":"n3","features":[]},{"relation":"relation:11","from":"n1","to":"n4","features":[]}],"stance":{"features":[{"feature":"feature:18","value":{"Grade":600}},{"feature":"feature:11","value":{"Grade":450}},{"feature":"feature:17","value":{"Grade":250}}]}}"#;
const PRESCRIBED: &str = r#"{"confidence":720,"context":{"setting":null,"medium":null,"participants":["n1"],"audience":["n1"]},"discourse":{"speech_act":"speech_act:3","addressee":null,"addressee_consent":null,"features":[]},"referents":[{"id":"n1","kind":"referent_kind:1","concept":"concept:28","entity":"entity:keeper","features":[]},{"id":"n2","kind":"referent_kind:1","concept":"concept:31","entity":null,"features":[]},{"id":"n3","kind":"referent_kind:5","concept":"concept:123","entity":null,"features":[]},{"id":"n4","kind":"referent_kind:5","concept":"concept:123","entity":null,"features":[]},{"id":"n7","kind":"referent_kind:2","concept":"concept:123","entity":null,"features":[]}],"predications":[{"id":"n5","concept":"concept:26","frame":"frame:4","roles":[{"role":"role:1","filler":"n1"},{"role":"role:2","filler":"n7"}],"features":[{"feature":"feature:1","value":{"Option":"positive"}},{"feature":"feature:2","value":{"Option":"present"}},{"feature":"feature:3","value":{"Option":"habitual"}}]},{"id":"n6","concept":"concept:196","frame":"frame:4","roles":[{"role":"role:1","filler":"n1"},{"role":"role:2","filler":"n5"}],"features":[{"feature":"feature:1","value":{"Option":"positive"}},{"feature":"feature:2","value":{"Option":"future"}},{"feature":"feature:4","value":{"Option":"desired"}}]}],"relations":[{"relation":"relation:11","from":"n2","to":"n3","features":[]},{"relation":"relation:11","from":"n1","to":"n4","features":[]},{"relation":"relation:3","from":"n3","to":"n7","features":[]},{"relation":"relation:3","from":"n4","to":"n7","features":[]}],"stance":{"features":[{"feature":"feature:18","value":{"Grade":600}},{"feature":"feature:11","value":{"Grade":450}},{"feature":"feature:17","value":{"Grade":250}}]}}"#;
let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../data/original/inventory.cc");
let inventory = InventoryStore::open(&path).unwrap().inventory().unwrap();
let item = CorpusItemId::parse("item:original-ja:19").unwrap();
let encoder = encoder_id("m", "d");
let packet = |answer: &str| {
PacketDraft::parse(answer)
.unwrap()
.into_packet(&item, 6, &encoder)
};
assert_eq!(
validate(&packet(REFUSED), &inventory),
Err(vec![Refusal::V11DuplicateRole {
role: "role:2".parse().unwrap(),
predication: "n5".parse().unwrap(),
}])
);
assert_eq!(validate(&packet(PRESCRIBED), &inventory), Ok(()));
// The prompt names the shape the packet above admits, by gloss.
let gloss = |id: &str| inventory.entry(&id.parse().unwrap()).unwrap().gloss.clone();
assert_eq!(gloss("referent_kind:2"), "group");
assert_eq!(gloss("relation:3"), "member_of");
let prompt = crate::context::ENCODE_INSTRUCTIONS;
assert!(prompt.contains("member_of") && prompt.contains("group"));
}
#[test]
fn lowering_draft_parse() {
let draft = LoweringDraft::parse("\n {\"text\":\"a\"} \n").unwrap();

View file

@ -252,6 +252,10 @@ pair a role id with a filler node (the inventory seeds `agent`, `patient`,
aspect, polarity, modality and evidentiality are features with declared option
sets, not fields.
A predication holds each role once (V11). Coordinated fillers ("A and B") are
one `group` referent filling the role, each member related to it by `member_of`,
from the member to the group.
### `relations`
Edges not owned by one predication. `relation` is a relation id (the inventory