Packet carries an addressee-consent fact (schema v5, V14, V15)
Discourse.addressee_consent names the predication the addressee asked for or agreed to. V4 checks it resolves, V14 needs an addressee and a predication, V15 allows only Authored or GameTelemetry sources. The English lowerer renders no consent and refuses a packet carrying one. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
73ce2de07f
commit
81572b1a54
10 changed files with 139 additions and 10 deletions
|
|
@ -139,6 +139,9 @@ pub fn lower(
|
|||
{
|
||||
return unrendered("features");
|
||||
}
|
||||
if input.discourse().addressee_consent.is_some() {
|
||||
return unrendered("addressee consent");
|
||||
}
|
||||
if !input.relations().is_empty() {
|
||||
return unrendered("relations");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub use crate::inventory::InvId;
|
|||
use crate::inventory::OptionLabel;
|
||||
|
||||
/// Bumped by a commit that changes these types; the published schema moves with it.
|
||||
pub const SCHEMA_VERSION: u32 = 4;
|
||||
pub const SCHEMA_VERSION: u32 = 5;
|
||||
|
||||
/// Id of a referent or predication within one packet: `n<k>`, `k` a canonical
|
||||
/// decimal 1..=9999.
|
||||
|
|
@ -261,6 +261,13 @@ pub struct Discourse {
|
|||
/// Speech-act id.
|
||||
pub speech_act: Option<InvId>,
|
||||
pub addressee: Option<NodeId>,
|
||||
/// The predication the addressee asked for or agreed to. A fact about what
|
||||
/// the addressee did, never about how the line sounds, so it is no feature:
|
||||
/// only a source that saw the request may set it (V15), it needs an
|
||||
/// addressee (V14) and names a predication (V14), and a lowering that
|
||||
/// speaks for the addressee's request ("you asked her to") reads it here
|
||||
/// and refuses without it.
|
||||
pub addressee_consent: Option<NodeId>,
|
||||
pub features: Vec<FeatureValue>,
|
||||
}
|
||||
|
||||
|
|
@ -385,6 +392,7 @@ pub fn proof_packet() -> Packet {
|
|||
discourse: Discourse {
|
||||
speech_act: Some(id("speech_act:5")),
|
||||
addressee: Some(node("n1")),
|
||||
addressee_consent: None,
|
||||
features: vec![],
|
||||
},
|
||||
referents: vec![
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
//! returns `Ok(())` or the refusals. [`LoweringInput`], the only thing a
|
||||
//! lowerer sees, comes from `PacketStore::admit` alone, which builds it through
|
||||
//! the crate-private `admissible`. The stance is checked like every feature
|
||||
//! list, in slot `Stance`. The rules are V1..V8 and V10..V13: the shape of an id
|
||||
//! list, in slot `Stance`. The rules are V1..V8 and V10..V15: the shape of an id
|
||||
//! or a grade is its type's parse, not a rule, so V9 is retired and not
|
||||
//! renumbered. V13 guards the one other way features reach a lowering view:
|
||||
//! [`LoweringInput::with_scene`].
|
||||
|
|
@ -29,7 +29,7 @@ use std::fmt;
|
|||
use crate::inventory::{Family, InvId, Inventory, InventoryEntry, Slot, ValueKind};
|
||||
use crate::packet::{
|
||||
Constraints, Context, Discourse, Extension, FeatValue, FeatureValue, NodeId, Packet,
|
||||
PacketKind, Predication, Referent, Relation, SCHEMA_VERSION, Stance,
|
||||
PacketKind, Predication, ProvenanceSource, Referent, Relation, SCHEMA_VERSION, Stance,
|
||||
};
|
||||
|
||||
/// A broken rule, named.
|
||||
|
|
@ -71,6 +71,15 @@ pub enum Refusal {
|
|||
/// state the speaker's relation to the addressee, so with none they
|
||||
/// describe nobody.
|
||||
V13SceneWithoutAddressee,
|
||||
/// V14: an addressee consent that no addressee can have given, or that
|
||||
/// names a node that is not a predication. It is what the addressee asked
|
||||
/// for or agreed to, an act, so a referent cannot be its object.
|
||||
V14ConsentWithoutAddressee,
|
||||
V14ConsentNotAPredication { id: NodeId },
|
||||
/// V15: an addressee consent set by a source that only read wording.
|
||||
/// A decomposition of text, or imported corpus text, sees "you asked her
|
||||
/// to" as words; only authoring or game telemetry saw the request.
|
||||
V15ConsentSource { source: ProvenanceSource },
|
||||
}
|
||||
|
||||
impl Refusal {
|
||||
|
|
@ -90,6 +99,10 @@ impl Refusal {
|
|||
| Refusal::V11DuplicateRole { .. } => "V11",
|
||||
Refusal::V12TooManyNodes { .. } => "V12",
|
||||
Refusal::V13SceneWithoutAddressee => "V13",
|
||||
Refusal::V14ConsentWithoutAddressee | Refusal::V14ConsentNotAPredication { .. } => {
|
||||
"V14"
|
||||
}
|
||||
Refusal::V15ConsentSource { .. } => "V15",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -156,6 +169,7 @@ pub(crate) fn admissible(
|
|||
let nodes = check_nodes(packet, &mut out);
|
||||
check_refs(packet, &nodes, &mut out);
|
||||
check_repeats(packet, &mut out);
|
||||
check_consent(packet, &nodes, &mut out);
|
||||
if inventory.has_revision(packet.inventory_rev) {
|
||||
Inventoried {
|
||||
inv: inventory,
|
||||
|
|
@ -208,6 +222,9 @@ fn check_refs(packet: &Packet, nodes: &BTreeSet<NodeId>, out: &mut Vec<Refusal>)
|
|||
if let Some(a) = &packet.discourse.addressee {
|
||||
need(a, "addressee");
|
||||
}
|
||||
if let Some(c) = &packet.discourse.addressee_consent {
|
||||
need(c, "addressee consent");
|
||||
}
|
||||
for (list, at) in node_lists(packet) {
|
||||
for id in list {
|
||||
need(id, at);
|
||||
|
|
@ -215,6 +232,26 @@ fn check_refs(packet: &Packet, nodes: &BTreeSet<NodeId>, out: &mut Vec<Refusal>)
|
|||
}
|
||||
}
|
||||
|
||||
/// V14 and V15: the addressee's consent is a typed fact with one origin. A
|
||||
/// dangling id is V4's, so V14 judges only a node that exists.
|
||||
fn check_consent(packet: &Packet, nodes: &BTreeSet<NodeId>, out: &mut Vec<Refusal>) {
|
||||
let Some(consent) = &packet.discourse.addressee_consent else {
|
||||
return;
|
||||
};
|
||||
if packet.discourse.addressee.is_none() {
|
||||
out.push(Refusal::V14ConsentWithoutAddressee);
|
||||
}
|
||||
if nodes.contains(consent) && !packet.predications.iter().any(|p| &p.id == consent) {
|
||||
out.push(Refusal::V14ConsentNotAPredication {
|
||||
id: consent.clone(),
|
||||
});
|
||||
}
|
||||
match packet.provenance.source {
|
||||
ProvenanceSource::Authored | ProvenanceSource::GameTelemetry => {}
|
||||
source => out.push(Refusal::V15ConsentSource { source }),
|
||||
}
|
||||
}
|
||||
|
||||
fn node_lists(packet: &Packet) -> [(&Vec<NodeId>, &'static str); 3] {
|
||||
[
|
||||
(&packet.context.participants, "participant"),
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@ pub fn good() -> Packet {
|
|||
discourse: Discourse {
|
||||
speech_act: Some(iv(WARN)),
|
||||
addressee: Some(nd("n1")),
|
||||
addressee_consent: None,
|
||||
features: vec![FeatureValue {
|
||||
feature: iv(HEDGE),
|
||||
value: FeatValue::Grade(grade(300)),
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ fn packet_entities_resolve() {
|
|||
|
||||
#[test]
|
||||
fn packet_schema_v2() {
|
||||
assert_eq!(SCHEMA_VERSION, 4);
|
||||
assert_eq!(SCHEMA_VERSION, 5);
|
||||
let mut p = good();
|
||||
p.schema_version = 2;
|
||||
let Err(refused) = validate(&p, &inventory()) else {
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ fn a_packet_carrying_what_the_lowerer_does_not_render_is_refused() {
|
|||
filler,
|
||||
})
|
||||
};
|
||||
let consent = |p: &mut Packet| p.discourse.addressee_consent = Some(nd("n5"));
|
||||
let lone_referent = |p: &mut Packet| {
|
||||
let mut r = p.referents[0].clone();
|
||||
r.id = nd("n99");
|
||||
|
|
@ -150,6 +151,7 @@ fn a_packet_carrying_what_the_lowerer_does_not_render_is_refused() {
|
|||
for (what, edit) in [
|
||||
("features", &discourse as &dyn Fn(&mut Packet)),
|
||||
("features", &predication),
|
||||
("addressee consent", &consent),
|
||||
("relations", &relation),
|
||||
("extensions", &extension),
|
||||
("no predication", &no_predication),
|
||||
|
|
|
|||
|
|
@ -989,14 +989,14 @@ fn packet_admission_goes_through_the_validator() {
|
|||
let mut w = world();
|
||||
let mut store = PacketStore::open(&w.dir.path().join("p.cc")).unwrap();
|
||||
let mut bad = good();
|
||||
bad.schema_version = 5;
|
||||
bad.schema_version = 6;
|
||||
match store.admit(bad, &w.inventory, &w.corpus, &w.entities) {
|
||||
Err(e @ StoreError::Invalid(_)) => {
|
||||
assert!(e.to_string().contains("V1"), "{e}");
|
||||
let StoreError::Invalid(r) = e else {
|
||||
unreachable!()
|
||||
};
|
||||
assert_eq!(r, vec![Refusal::V1SchemaVersion { found: 5 }]);
|
||||
assert_eq!(r, vec![Refusal::V1SchemaVersion { found: 6 }]);
|
||||
}
|
||||
other => panic!("{other:?}"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -683,3 +683,62 @@ fn v11_role_repeat_in_one_predication_refused() {
|
|||
ok.predications.push(second);
|
||||
assert_eq!(refusals(&ok), vec![]);
|
||||
}
|
||||
|
||||
// The addressee's consent: which predication the addressee asked for, set only
|
||||
// by a source that saw the request.
|
||||
|
||||
fn consenting() -> Packet {
|
||||
let mut p = good();
|
||||
p.discourse.addressee_consent = Some(nd("n2"));
|
||||
p
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn consent_to_a_predication_by_an_authored_or_telemetry_source_passes() {
|
||||
assert_eq!(refusals(&consenting()), vec![]);
|
||||
let mut p = consenting();
|
||||
p.provenance.source = ProvenanceSource::GameTelemetry;
|
||||
assert_eq!(refusals(&p), vec![]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn consent_needs_an_addressee() {
|
||||
let mut p = consenting();
|
||||
p.discourse.addressee = None;
|
||||
assert_eq!(refusals(&p), vec![Refusal::V14ConsentWithoutAddressee]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn consent_names_a_predication_not_a_referent() {
|
||||
let mut p = consenting();
|
||||
p.discourse.addressee_consent = Some(nd("n1"));
|
||||
assert_eq!(
|
||||
refusals(&p),
|
||||
vec![Refusal::V14ConsentNotAPredication { id: nd("n1") }]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn consent_to_nothing_is_dangling_only() {
|
||||
let mut p = consenting();
|
||||
p.discourse.addressee_consent = Some(nd("n99"));
|
||||
assert_eq!(
|
||||
refusals(&p),
|
||||
vec![Refusal::V4DanglingRef {
|
||||
id: nd("n99"),
|
||||
at: "addressee consent"
|
||||
}]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_source_that_only_read_wording_cannot_set_consent() {
|
||||
for source in [
|
||||
ProvenanceSource::ModelDecomposition,
|
||||
ProvenanceSource::ImportedCorpus,
|
||||
] {
|
||||
let mut p = consenting();
|
||||
p.provenance.source = source;
|
||||
assert_eq!(refusals(&p), vec![Refusal::V15ConsentSource { source }]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ Packet
|
|||
id, schema_version, inventory_rev, kind
|
||||
provenance { source, corpus_item, encoder, confidence }
|
||||
context { setting, medium, participants, audience }
|
||||
discourse { speech_act, addressee, features }
|
||||
discourse { speech_act, addressee, addressee_consent, features }
|
||||
referents [ { id, kind, concept, entity, features } ]
|
||||
predications [ { id, concept, frame, roles: [ { role, filler } ], features } ]
|
||||
relations [ { relation, from, to, features } ]
|
||||
|
|
@ -144,8 +144,8 @@ names the rule.
|
|||
- V1: `schema_version` is the version these types define.
|
||||
- V2: at least one of `referents`, `predications`, `relations` is present.
|
||||
- V3: a node id appears once across referents and predications.
|
||||
- V4: every role filler, relation end, addressee, participant, audience member
|
||||
and preserved node names a node.
|
||||
- V4: every role filler, relation end, addressee, addressee consent,
|
||||
participant, audience member and preserved node names a node.
|
||||
- V5: every inventory id resolves at the packet's `inventory_rev`: introduced
|
||||
at or before it, and not retired at or before it.
|
||||
- V6: an inventory id is of the family its slot takes.
|
||||
|
|
@ -159,6 +159,10 @@ names the rule.
|
|||
predication's roles.
|
||||
- V12: a packet has at most 64 referents, predications and relations together
|
||||
(a calibration constant, capacity and not meaning).
|
||||
- V14: an `addressee_consent` needs an `addressee` and names a predication.
|
||||
- V15: an `addressee_consent` is set only by provenance `Authored` or
|
||||
`GameTelemetry`; a decomposition of text or imported corpus text cannot mint
|
||||
it.
|
||||
|
||||
V9 is retired and not renumbered: the form of a key or a grade is its type, and
|
||||
an extension key's family is V6. `PacketStore::admit` returns the lowering view of a
|
||||
|
|
@ -189,7 +193,11 @@ ids.
|
|||
Why the packet is said: `speech_act` is a speech-act id, `addressee` a node id,
|
||||
and `features` carry source-side nuance on content (hedge, certainty, irony and
|
||||
whatever the inventory grows). This is source-side communicative pressure, not
|
||||
target-language register.
|
||||
target-language register. `addressee_consent` is no feature: it names the
|
||||
predication the addressee asked for or agreed to, a fact about what the
|
||||
addressee did. The English lowerer renders no consent and refuses a packet that
|
||||
carries one; a row that speaks for the request ("you asked her to") reads it
|
||||
and refuses without it.
|
||||
|
||||
### `stance`
|
||||
|
||||
|
|
|
|||
|
|
@ -164,6 +164,17 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"addressee_consent": {
|
||||
"description": "The predication the addressee asked for or agreed to. A fact about what\nthe addressee did, never about how the line sounds, so it is no feature:\nonly a source that saw the request may set it (V15), it needs an\naddressee (V14) and names a predication (V14), and a lowering that\nspeaks for the addressee's request (\"you asked her to\") reads it here\nand refuses without it.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/$defs/NodeId"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue