en-us-seed-pairs: en-US :3/:5/:6 made disjoint by conditions, shared sweep helper (#59)
This commit is contained in:
parent
981ad0ea1f
commit
ccef7a761f
4 changed files with 100 additions and 45 deletions
|
|
@ -95,7 +95,7 @@ addressee, and none for an above-status in-group addressee below intimacy 700 (`
|
|||
an in-group addressee at intimacy 700 or more, whatever the status). Two entries for the above-status
|
||||
cases were withdrawn: a paired measure found they made the lowerer match the reference register less
|
||||
often, and they stay out until a native reader attests them.
|
||||
ja-JP `:5` (hedging), `:7` (affection) and `:8` (restrained sadness) carry certainty and restraint conditions, through `AtMostOrUnset` bounds (an unrated certainty or restraint does not defeat them), so the hedging, certainty, affection, restraint and sadness entries never co-select on the pairs `:5`/`:6`, `:4`/`:7`, `:6`/`:7` and `:6`/`:8`; the store has no retire, so that was a rebuild of `data/ontology/ontology.cc` with the ja-JP text unchanged.
|
||||
ja-JP `:5` (hedging), `:7` (affection) and `:8` (restrained sadness) carry certainty and restraint conditions, through `AtMostOrUnset` bounds (an unrated certainty or restraint does not defeat them), so the hedging, certainty, affection, restraint and sadness entries never co-select on the pairs `:5`/`:6`, `:4`/`:7`, `:6`/`:7` and `:6`/`:8`; the store has no retire, so that was a rebuild of `data/ontology/ontology.cc` with the ja-JP text unchanged. en-US `:3` (blunt anger) carries `AtMostOrUnset` hedge and affection bounds and `:5` (hedging) an `AtMostOrUnset` certainty bound, so `:3`/`:5`, `:3`/`:8` and `:5`/`:6` never co-select; `:5`'s certainty clause is that condition and no longer prose; `:6` and the Scene entry `:10` still co-select and are kept apart by scoping in the text.
|
||||
|
||||
For the first AquaSynth speech-training handoff, see
|
||||
[Tiny PanPhon v0.1 Speech Curriculum](./examples/speech-training/tiny-panphon-v0.1/README.md).
|
||||
|
|
|
|||
|
|
@ -961,14 +961,18 @@ fn committed_scenes_cover_original_groups() {
|
|||
}
|
||||
}
|
||||
|
||||
/// ja-JP seed entries :4 to :8 over the stance and discourse grades that bear on
|
||||
/// them (hedge, certainty, sadness, affection, restraint, each also ABSENT):
|
||||
/// the pairs that gave opposed instructions (hedge against certainty,
|
||||
/// particles, final force) never hold together; and each of :5, :7, :8 still
|
||||
/// fires where it should (hedged at certainty 700-799, affection with certainty
|
||||
/// or restraint unrated), so a tightened bound does not pass as a disjoint one.
|
||||
#[test]
|
||||
fn ja_seed_pairs_never_co_select() {
|
||||
/// The sweep both seed-pair tests share: over a grid of grades per feature (each
|
||||
/// also ABSENT) and the production `Condition::holds`, no listed pair of one
|
||||
/// language's entries co-holds; and each witness entry fires where it should and
|
||||
/// stays silent where it should, so a tightened or dropped bound does not pass
|
||||
/// as a disjoint one. `glosses` names the swept features, in point order.
|
||||
fn sweep_seed_pairs<const N: usize>(
|
||||
language: &str,
|
||||
glosses: [&str; N],
|
||||
pairs: &[(u32, u32)],
|
||||
fires: &[(u32, [Option<u16>; N])],
|
||||
silent: &[(u32, [Option<u16>; N])],
|
||||
) {
|
||||
use weksa::inventory::Slot;
|
||||
use weksa::ontology::{Condition, Test};
|
||||
use weksa::OntologyStore;
|
||||
|
|
@ -978,18 +982,18 @@ fn ja_seed_pairs_never_co_select() {
|
|||
std::fs::copy(data.join("ontology/ontology.cc"), &onto).unwrap();
|
||||
let inv = InventoryStore::open(&data.join("original/inventory.cc")).unwrap().inventory().unwrap();
|
||||
let id = |gloss: &str| inv.entries().find(|e| e.gloss == gloss).unwrap().id;
|
||||
let feats = [id("hedge"), id("certainty"), id("sadness"), id("affection"), id("restraint")];
|
||||
let feats = glosses.map(id);
|
||||
let entries = OntologyStore::open(&onto).unwrap().all().unwrap();
|
||||
let ja = |n: u32| {
|
||||
let entry = |n: u32| {
|
||||
entries
|
||||
.iter()
|
||||
.find(|e| e.language == "ja-JP" && e.n == n)
|
||||
.unwrap_or_else(|| panic!("onto:ja-JP:{n} is absent"))
|
||||
.find(|e| e.language == language && e.n == n)
|
||||
.unwrap_or_else(|| panic!("onto:{language}:{n} is absent"))
|
||||
};
|
||||
type Point = [Option<u16>; 5];
|
||||
type Point<const N: usize> = [Option<u16>; N];
|
||||
// The production evaluator over the slot's feature values: absent features
|
||||
// are left out of the list, as a view leaves them out.
|
||||
let holds = |e: &weksa::OntologyEntry, point: &Point| {
|
||||
let holds = |e: &weksa::OntologyEntry, point: &Point<N>| {
|
||||
use weksa::packet::{FeatValue, FeatureValue, Grade};
|
||||
e.when.iter().all(|c: &Condition| {
|
||||
assert!(matches!(c.slot, Slot::Stance | Slot::Discourse), "{}", e.key());
|
||||
|
|
@ -1010,45 +1014,96 @@ fn ja_seed_pairs_never_co_select() {
|
|||
})
|
||||
};
|
||||
let grid = [None, Some(0u16), Some(300), Some(500), Some(599), Some(600), Some(700), Some(799), Some(800), Some(1000)];
|
||||
let pairs = [(5, 6), (4, 7), (6, 7), (6, 8)];
|
||||
for p in 0..grid.len().pow(5) {
|
||||
let point: Point = std::array::from_fn(|i| grid[p / grid.len().pow(i as u32) % grid.len()]);
|
||||
for (a, b) in pairs {
|
||||
for p in 0..grid.len().pow(N as u32) {
|
||||
let point: Point<N> = std::array::from_fn(|i| grid[p / grid.len().pow(i as u32) % grid.len()]);
|
||||
for &(a, b) in pairs {
|
||||
assert!(
|
||||
!(holds(ja(a), &point) && holds(ja(b), &point)),
|
||||
"onto:ja-JP:{a} and :{b} co-select at (hedge, certainty, sadness, affection, restraint) = {point:?}"
|
||||
!(holds(entry(a), &point) && holds(entry(b), &point)),
|
||||
"onto:{language}:{a} and :{b} co-select at {glosses:?} = {point:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
// Reach: each entry fires at its witnesses and not just outside its core.
|
||||
let (n, s) = (None, Some);
|
||||
let fires: [(u32, Point); 9] = [
|
||||
(5, [s(600), n, n, n, n]),
|
||||
(5, [s(700), s(799), n, n, n]),
|
||||
(5, [s(700), n, n, n, n]),
|
||||
(7, [n, s(799), n, s(700), s(599)]),
|
||||
(7, [n, n, n, s(700), n]),
|
||||
(7, [s(1000), s(0), s(1000), s(600), s(0)]),
|
||||
(8, [n, s(799), s(700), n, s(700)]),
|
||||
(8, [n, n, s(600), n, s(600)]),
|
||||
(6, [n, s(800), n, n, n]),
|
||||
];
|
||||
for (e, point) in fires {
|
||||
assert!(holds(ja(e), &point), "onto:ja-JP:{e} does not fire at {point:?}");
|
||||
assert!(holds(entry(*e), point), "onto:{language}:{e} does not fire at {point:?}");
|
||||
}
|
||||
let silent: [(u32, Point); 6] = [
|
||||
(8, [n, n, s(599), n, s(700)]),
|
||||
(8, [n, n, n, n, s(700)]),
|
||||
(5, [s(599), n, n, n, n]),
|
||||
(7, [n, n, n, s(599), n]),
|
||||
(7, [n, n, n, s(700), s(600)]),
|
||||
(8, [n, n, s(600), n, s(599)]),
|
||||
];
|
||||
for (e, point) in silent {
|
||||
assert!(!holds(ja(e), &point), "onto:ja-JP:{e} fires at {point:?}");
|
||||
assert!(!holds(entry(*e), point), "onto:{language}:{e} fires at {point:?}");
|
||||
}
|
||||
}
|
||||
|
||||
/// ja-JP seed entries :4 to :8 over the stance and discourse grades that bear on
|
||||
/// them (hedge, certainty, sadness, affection, restraint): the pairs that gave
|
||||
/// opposed instructions (hedge against certainty, particles, final force) never
|
||||
/// hold together; and each of :5, :7, :8 still fires where it should (hedged at
|
||||
/// certainty 700-799, affection with certainty or restraint unrated).
|
||||
#[test]
|
||||
fn ja_seed_pairs_never_co_select() {
|
||||
let (n, s) = (None, Some);
|
||||
sweep_seed_pairs(
|
||||
"ja-JP",
|
||||
["hedge", "certainty", "sadness", "affection", "restraint"],
|
||||
&[(5, 6), (4, 7), (6, 7), (6, 8)],
|
||||
&[
|
||||
(5, [s(600), n, n, n, n]),
|
||||
(5, [s(700), s(799), n, n, n]),
|
||||
(5, [s(700), n, n, n, n]),
|
||||
(7, [n, s(799), n, s(700), s(599)]),
|
||||
(7, [n, n, n, s(700), n]),
|
||||
(7, [s(1000), s(0), s(1000), s(600), s(0)]),
|
||||
(8, [n, s(799), s(700), n, s(700)]),
|
||||
(8, [n, n, s(600), n, s(600)]),
|
||||
(6, [n, s(800), n, n, n]),
|
||||
],
|
||||
&[
|
||||
(8, [n, n, s(599), n, s(700)]),
|
||||
(8, [n, n, n, n, s(700)]),
|
||||
(5, [s(599), n, n, n, n]),
|
||||
(7, [n, n, n, s(599), n]),
|
||||
(7, [n, n, n, s(700), s(600)]),
|
||||
(8, [n, n, s(600), n, s(599)]),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// en-US seed entries :3, :5, :6, :8 over anger, restraint, hedge, certainty and
|
||||
/// affection: blunt anger never holds with a hedge or affection entry, and a
|
||||
/// hedge never holds with a flatly certain line, so the pairs that gave opposed
|
||||
/// instructions (no cushioning against softening, hedge against no hedge) are
|
||||
/// disjoint by condition; each of :3, :5, :6, :8 fires and stays silent at its
|
||||
/// witnesses, so a dropped or tightened bound does not pass as a disjoint one.
|
||||
/// :6 against the Scene entry :10 is kept apart by scoping in the text only.
|
||||
#[test]
|
||||
fn en_us_seed_pairs_never_co_select() {
|
||||
let (n, s) = (None, Some);
|
||||
sweep_seed_pairs(
|
||||
"en-US",
|
||||
["anger", "restraint", "hedge", "certainty", "affection"],
|
||||
&[(3, 5), (3, 8), (5, 6)],
|
||||
&[
|
||||
(3, [s(600), s(300), n, n, n]),
|
||||
(3, [s(600), s(300), s(599), n, s(599)]),
|
||||
(3, [s(1000), s(0), s(0), s(799), s(0)]),
|
||||
(5, [n, n, s(600), n, n]),
|
||||
(5, [n, n, s(700), s(799), n]),
|
||||
(5, [s(1000), s(1000), s(600), n, n]),
|
||||
(6, [n, n, n, s(800), n]),
|
||||
(8, [n, n, n, n, s(600)]),
|
||||
(8, [s(1000), s(0), n, n, s(600)]),
|
||||
],
|
||||
&[
|
||||
(3, [s(600), s(300), s(600), n, n]),
|
||||
(3, [s(600), s(300), n, n, s(600)]),
|
||||
(3, [s(599), s(300), n, n, n]),
|
||||
(3, [s(600), s(301), n, n, n]),
|
||||
(3, [s(600), n, n, n, n]),
|
||||
(5, [n, n, s(599), n, n]),
|
||||
(5, [n, n, s(700), s(800), n]),
|
||||
(6, [n, n, n, s(799), n]),
|
||||
(8, [n, n, n, n, s(599)]),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// The committed ontology's Scene-conditioned entries, over every scene relation
|
||||
/// (relative_status x in_group x intimacy in steps of 50): two entries of one
|
||||
/// language and layer are never selected by the same relation, so the ontology
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -34,7 +34,7 @@ means no store holds it and nothing writes it.
|
|||
| Inventory entry | Key `<family>:<n>`, `n` canonical decimal >= 1 (families: concept, frame, role, relation, speech_act, feature, referent_kind, extension); type `weksa.inventory_entry`, with a bounded gloss, value kind (option labels bounded), the slots a feature may sit in (`Discourse`, `Referent`, `Predication`, `Relation`; `Stance` from cut `speaker-state`, `Speaker` and `Scene` from cut `speaker-scene`), `introduced_rev` and optional `retired_rev`. Speaker axes, scene relations and affects are features of those slots, so the loop grows them like any closed-class family and convergence covers them | Added or retired by an inventory revision; never edited in place (a changed meaning is a retire plus an add); a retired id still resolves for packets of earlier revisions | The loop's accepted rounds, whose minting call the context builder assembles from Train items only; `weksa inventory admit` for one model-drafted `EditDraft` outside a run (cap 256, reviewed whole in its cut; same numbering and admission check as the loop); Self on merge to main. `data/original` revs 5 (233 concepts and frames) and 6 (five concepts closing named gaps) were drafted by claude-sonnet-5-5 (Weksa Hands, model-drafted original-bed lexicon from Train and Validation passages); Validation-informed: numbers on this bed measure lowering, never generalization or convergence. Residue after rev 6, not amended (each fresh coverage reader names new gaps; the loop's growth path owns them): simultaneity (ながら), distal deixis (あの), 'first' (まず), counterfactual mood, 'at least', emphatic question; heaven versus sky for the visible 天 stays weak. Admission checks form, not text |
|
||||
| Inventory revision | Key `rev:<n>`, type `weksa.inventory_revision`, with parent, change list and `frozen` | Appended per accepted round; exactly one revision is ever marked frozen, by the convergence test | The loop's accept rule appends; the convergence test freezes; Self records the freeze as a ruling |
|
||||
| Target profile | Locale or language-project id (`en-US`, `ja-JP`, a conlang's slug). Until entries grow in rounds there is no profile revision document: a run names the profile it lowered with by the ontology store's path and digest in its `RunRecord` (cut `language-ontology`); `profile:<language>:<n>` revision documents arrive with follow-up `language-ontology-growth` | The ontology store is revised by commit; a run pins it and refuses drift; it likewise pins the speaker-state store (`RunRecord` keys 17 and 18, `Drift(SpeakerState)`, cut `language-ontology-scene`) | Profile authors and accepted rounds; never the lowerer's defaults (`persona-drives-register`) |
|
||||
| Language ontology entry (cut `language-ontology`) | Key `onto:<language>:<n>`, `n` from 1 per language; type `weksa.ontology_entry` in `data/ontology/ontology.cc`: the language, the revision of the inventory it was admitted through (provenance: beds number revisions independently and a run reads each condition's feature at its own head), a layer (lexicon, grammar, discourse, phonology, orthography), at most four conditions (a feature id of slot `Stance`, `Discourse` or `Scene` with `AtLeast`/`AtMost`/`AtMostOrUnset` a grade or `Is` an option or flag; a `Scene` condition reads the relation of the item's speaker to its addressee that `with_scene` selected; slot `Speaker` and community ids wait on follow-up `language-ontology-communities`), a choice of 1 to 200 bytes, at most three examples of 1 to 120 bytes, and an `Annotator`. Whether an entry's text keeps politeness on the scene is a model reader's judgment, owed per change (a mint owes it under `language-ontology-growth`), not a test | Admitted in all-or-nothing batches through `OntologyStore::admit`, immutable, never edited; retire arrives with `language-ontology-growth`. The run pins the store like the entity store (path and digest, `Drift(Ontology)`), never copies it, because no loop step writes it yet. Cut `language-ontology-seed` converts by drafting, not by parse: a fresh model drafts each language's seed from that language's YAML and the inventory's feature lines with no corpus text, then deletes `data/target-language-ontology/` and `.weksa/cultural-ontology/` in the same cut | Seed: a labelled model (`Annotator::Model`), no operator gate, never Test evidence (`ja-ontology-owner-answer`); attestation (operator, native reader) appends later. Accepted rounds later, through a mint call from Train items only. Selection is `ontology::select(ontology, language, view)`, called only inside `Prompt::lower`, so no caller picks entries; the prompt prints each selected entry's id, layer, choice and examples. Its text is minted text for the leak diagnostic, which today has no runtime caller (follow-up `leak-diagnostic-in-round`). The store was rebuilt without ja-JP `:14` and `:15` (above-status Scene entries; a paired measure found them net-negative on register, follow-up `ja-scene-entries-lower-register-agreement`), so ja-JP ends at `:13`: an above-status out-group addressee, and an above-status in-group addressee below intimacy 700, select no ja-JP Scene entry (`:12` still selects in-group at intimacy 700 or more regardless of status) until a native reader attests a replacement (`ja-native-reader-scenes`). ja-JP `:5`, `:7` and `:8` were revised by certainty and restraint `AtMostOrUnset` conditions (holds when the feature is unrated or at most the grade; `AtMost` still fails on an unrated feature) in a store rebuild (the store has no retire, so a conditions change is a rebuild), which makes ja-JP's hedging, certainty, affection, restraint and sadness entries disjoint on `:5`/`:6`, `:4`/`:7`, `:6`/`:7`, `:6`/`:8` |
|
||||
| Language ontology entry (cut `language-ontology`) | Key `onto:<language>:<n>`, `n` from 1 per language; type `weksa.ontology_entry` in `data/ontology/ontology.cc`: the language, the revision of the inventory it was admitted through (provenance: beds number revisions independently and a run reads each condition's feature at its own head), a layer (lexicon, grammar, discourse, phonology, orthography), at most four conditions (a feature id of slot `Stance`, `Discourse` or `Scene` with `AtLeast`/`AtMost`/`AtMostOrUnset` a grade or `Is` an option or flag; a `Scene` condition reads the relation of the item's speaker to its addressee that `with_scene` selected; slot `Speaker` and community ids wait on follow-up `language-ontology-communities`), a choice of 1 to 200 bytes, at most three examples of 1 to 120 bytes, and an `Annotator`. Whether an entry's text keeps politeness on the scene is a model reader's judgment, owed per change (a mint owes it under `language-ontology-growth`), not a test | Admitted in all-or-nothing batches through `OntologyStore::admit`, immutable, never edited; retire arrives with `language-ontology-growth`. The run pins the store like the entity store (path and digest, `Drift(Ontology)`), never copies it, because no loop step writes it yet. Cut `language-ontology-seed` converts by drafting, not by parse: a fresh model drafts each language's seed from that language's YAML and the inventory's feature lines with no corpus text, then deletes `data/target-language-ontology/` and `.weksa/cultural-ontology/` in the same cut | Seed: a labelled model (`Annotator::Model`), no operator gate, never Test evidence (`ja-ontology-owner-answer`); attestation (operator, native reader) appends later. Accepted rounds later, through a mint call from Train items only. Selection is `ontology::select(ontology, language, view)`, called only inside `Prompt::lower`, so no caller picks entries; the prompt prints each selected entry's id, layer, choice and examples. Its text is minted text for the leak diagnostic, which today has no runtime caller (follow-up `leak-diagnostic-in-round`). The store was rebuilt without ja-JP `:14` and `:15` (above-status Scene entries; a paired measure found them net-negative on register, follow-up `ja-scene-entries-lower-register-agreement`), so ja-JP ends at `:13`: an above-status out-group addressee, and an above-status in-group addressee below intimacy 700, select no ja-JP Scene entry (`:12` still selects in-group at intimacy 700 or more regardless of status) until a native reader attests a replacement (`ja-native-reader-scenes`). ja-JP `:5`, `:7` and `:8` were revised by certainty and restraint `AtMostOrUnset` conditions (holds when the feature is unrated or at most the grade; `AtMost` still fails on an unrated feature) in a store rebuild (the store has no retire, so a conditions change is a rebuild), which makes ja-JP's hedging, certainty, affection, restraint and sadness entries disjoint on `:5`/`:6`, `:4`/`:7`, `:6`/`:7`, `:6`/`:8`; en-US `:3` carries `AtMostOrUnset` hedge and affection bounds and `:5` an `AtMostOrUnset` certainty bound (the clause it held in prose), which makes `:3`/`:5`, `:3`/`:8` and `:5`/`:6` disjoint, while `:6`/`:10` stay co-selectable and are kept apart by scoping in `:6`'s text |
|
||||
| Community (cut `language-ontology`, follow-up `language-ontology-communities`) | Key `community:<slug>`; type `weksa.community`, converted from `data/cultural-ontology/cultures/` and `referents/` (YAML deleted in the same cut) | Revised by commit; a speaker names the communities it belongs to by id | The cultural ontology's author (owner-attested evidence only; Discord-only content stays deleted, `discord-only-content-deleted`) |
|
||||
| Speaker (cut `speaker-scene`) | Key `speaker:<slug>@<n>`; type `weksa.speaker`: stable axes as feature values of slot `Speaker` (origin, socioeconomic standing, age cohort, education and whatever the loop adds), at an inventory revision, and an `Annotator` | A new revision appends, never edits; a corpus item and every prior turn name a speaker slug, and a round records the speaker revisions it read | The annotator it names: `PersonaSnapshot` (a projection of a `gamecult.persona_state.v0` document, naming its source document and `updatedAt`), `Operator`, `WorkMetadata` (a public-domain work's own cast list and narration), or `Model { family, generator }` (the 2b `ModelFamily`) |
|
||||
| Scene (cut `speaker-scene`) | Key `scene:<group>@<n>`, the item's split group; type `weksa.scene`: participants (speaker slugs) and, per ordered pair, relation features of slot `Scene` (relative status, intimacy, in-group, audience and whatever the loop adds), at an inventory revision (provenance; a run reads the features at its own head), and an `Annotator` | As Speaker. Keyed by the group, so a scene never straddles the split. `data/original/speaker-state.cc` holds Model-annotated keeper scenes, one per Train or Validation group of both languages (`weksa scene put|dump`); a Test group has none and reads `NoScene` | As Speaker; a model-annotated scene is never Test evidence |
|
||||
|
|
|
|||
Loading…
Reference in a new issue