What happens to one thing the child says, as data: the steps a turn takes, where Jev is asked
something, and where a turn can end in a fixed line instead of an answer. The website draws its
diagram from this, and tests/conversation.rs runs the real pipeline into every exit listed
here, so the picture cannot show a step or an ending the code does not have.
This is a description of Conversation::respond, not the thing that runs it: the order of the
steps is the order of the code, and a test that disagrees fails.
9use crate::types::{Direction, Fallback};
On the child's tablet, in the Rust core.
15 Tablet,
The language model, through the household's gateway.
17 Model,
Which way the message travels past the guard; None for a question that is not a check.
26 pub direction: Option<Direction>,
A way a step can end the turn, and what the child hears instead.
Why, in plain words. Unique within its step: the tests find the scenario by it.
Whether the step happens only when the child showed a picture.
What the step writes in the parents' log when it passes, as the event's name.
54const REFUSED: Exit = Exit { cause: "refused", then: Fallback::ChildRefused, parents_see: "the refusal and its reason" }; 55const GROWN_UP: Exit = Exit { 56 cause: "refused: she is hurt, unsafe or asked to keep a secret", 57 then: Fallback::NeedsAGrownUp, 58 parents_see: "the refusal, shown first", 59}; 60const JEV_DOWN: Exit = Exit { cause: "Jev cannot be reached", then: Fallback::GuardUnavailable, parents_see: "a failure at the check" };
The turn, in order.
63pub const TURN: [Step; 9] = [ 64 Step { 65 id: "keep-pictures", 66 place: Place::Tablet, 67 what: "Any picture she shows is kept before anything is sent anywhere.", 68 jev: None, 69 only_with_pictures: true, 70 exits: &[Exit { cause: "a picture cannot be kept", then: Fallback::LogUnavailable, parents_see: "nothing: the log is what broke" }], 71 logs: "", 72 }, 73 Step { 74 id: "log-heard", 75 place: Place::Tablet, 76 what: "What she said is written to the parents' log, before the guard or the model sees it.", 77 jev: None, 78 only_with_pictures: false, 79 exits: &[Exit { cause: "the log cannot be written", then: Fallback::LogUnavailable, parents_see: "nothing: the log is what broke" }], 80 logs: "Heard", 81 }, 82 Step { 83 id: "check-words", 84 place: Place::Jev, 85 what: "Jev is asked whether what she said is fit for a child of her age to say to the cat.", 86 jev: Some(JevCheck { direction: Some(Direction::FromChild), asks: "May this be said?" }), 87 only_with_pictures: false, 88 exits: &[REFUSED, GROWN_UP, JEV_DOWN], 89 logs: "Guarded", 90 }, 91 Step { 92 id: "describe-picture", 93 place: Place::Model, 94 what: "A picture is first described in plain words by a model call that has no persona.", 95 jev: None, 96 only_with_pictures: true, 97 exits: &[Exit { cause: "the model cannot be reached", then: Fallback::ModelUnavailable, parents_see: "a failure at the model" }], 98 logs: "PictureSeen", 99 }, 100 Step { 101 id: "check-picture", 102 place: Place::Jev, 103 what: "Jev reads only words, so the description is judged exactly as her speech is.", 104 jev: Some(JevCheck { direction: Some(Direction::FromChild), asks: "May this be said?" }), 105 only_with_pictures: true, 106 exits: &[REFUSED, GROWN_UP, JEV_DOWN], 107 logs: "Guarded", 108 }, 109 Step { 110 id: "recall", 111 place: Place::Jev, 112 what: "What the cat remembers is searched by meaning. When more than four memories fit, Jev orders them; fewer, and nothing is asked. This only adds: it never ends a turn.", 113 jev: Some(JevCheck { direction: None, asks: "Which memory helps most?" }), 114 only_with_pictures: false, 115 exits: &[], 116 logs: "Recalled", 117 }, 118 Step { 119 id: "model-writes", 120 place: Place::Model, 121 what: "The model writes a reply, from the parents' prompt, the memories and a window of the chat.", 122 jev: None, 123 only_with_pictures: false, 124 exits: &[ 125 Exit { cause: "the model cannot be reached", then: Fallback::ModelUnavailable, parents_see: "a failure at the model" }, 126 Exit { cause: "the allowance for thinking is used up", then: Fallback::Resting, parents_see: "a failure at the model, said as a rest" }, 127 ], 128 logs: "ModelWrote", 129 }, 130 Step { 131 id: "check-answer", 132 place: Place::Jev, 133 what: "Jev is asked whether what the model wrote is fit for her to hear.", 134 jev: Some(JevCheck { direction: Some(Direction::ToChild), asks: "May this be heard?" }), 135 only_with_pictures: false, 136 exits: &[ 137 Exit { cause: "refused", then: Fallback::AnswerRefused, parents_see: "what the model wrote, and the refusal" }, 138 JEV_DOWN, 139 ], 140 logs: "Guarded", 141 }, 142 Step { 143 id: "say", 144 place: Place::Tablet, 145 what: "The tablet speaks the answer.", 146 jev: None, 147 only_with_pictures: false, 148 exits: &[], 149 logs: "Said", 150 }, 151];
Every place the app asks Jev something, in the code. Three are steps of a turn; the others
(a fact to remember, a chat summary) happen after it, off to the side (reflect.rs).
163pub const JEV_USES: [JevUse; 6] = [ 164 JevUse { id: "check-words", asks: "Is what she said fit for her age, and what is it about?", on_failure: "refused: the cat says a fixed line" }, 165 JevUse { id: "check-picture", asks: "The same two questions, of the words that describe her picture.", on_failure: "refused: the cat says a fixed line" }, 166 JevUse { id: "check-answer", asks: "The same two questions, of what the model wrote.", on_failure: "refused: she hears a fixed line instead" }, 167 JevUse { id: "check-fact", asks: "The same two questions, of a fact the cat is about to remember about her.", on_failure: "the fact is not kept, and the log says so" }, 168 JevUse { id: "check-summary", asks: "The same two questions, of the summary that stands in for a long chat.", on_failure: "the chat is left as it was" }, 169 JevUse { id: "rank-memories", asks: "Which of these remembered things helps most with what she just said?", on_failure: "the cat remembers by meaning alone" }, 170];
Things that are not Jev, so the page does not credit it with them.
173pub const NOT_JEV: [(&str, &str); 6] = [ 174 ("Writing the cat's words", "The language model does, through the household's gateway. Jev never writes text."), 175 ("Understanding speech", "The tablet turns her voice into text before anything else happens."), 176 ("Reading pictures", "A model call describes a picture in words; Jev only judges those words."), 177 ("Finding memories by meaning", "A separate embedding model on the household's own machine turns text into vectors; Jev only orders the shortlist."), 178 ("The allowance and the bedtime", "Plain rules in the core: minutes a day and quiet hours."), 179 ("The parents' log", "Written by the core before each step. Jev is not asked to remember anything."), 180];
182#[cfg(test)] 183mod tests { 184 use super::*; 185 186 #[test] 187 fn ids_are_unique_and_causes_are_unique_within_a_step() { 188 for (i, a) in TURN.iter().enumerate() { 189 assert!(TURN.iter().skip(i + 1).all(|b| b.id != a.id), "{}", a.id); 190 for (j, x) in a.exits.iter().enumerate() { 191 assert!(a.exits.iter().skip(j + 1).all(|y| y.cause != x.cause), "{} {}", a.id, x.cause); 192 } 193 } 194 } 195 196 #[test] 197 fn every_fixed_line_the_cat_can_say_is_an_exit_of_some_step() { 198 for fallback in Fallback::ALL { 199 assert!(TURN.iter().any(|s| s.exits.iter().any(|e| e.then == fallback)), "{fallback:?} ends no step"); 200 } 201 } 202 203 #[test] 204 fn a_step_that_asks_jev_is_placed_at_jev_and_the_others_are_not() { 205 for step in TURN { 206 assert_eq!(step.jev.is_some(), step.place == Place::Jev, "{}", step.id); 207 } 208 } 209 210 #[test] 211 fn every_jev_step_of_the_turn_is_a_use_and_every_use_has_a_failure() { 212 for step in TURN.iter().filter(|s| s.jev.is_some()) { 213 let id = if step.id == "recall" { "rank-memories" } else { step.id }; 214 assert!(JEV_USES.iter().any(|u| u.id == id), "{}", step.id); 215 } 216 assert!(JEV_USES.iter().all(|u| !u.on_failure.is_empty())); 217 } 218}