From 732ed009f2d8b8ea5942b243ae8209f1dd755b7e Mon Sep 17 00:00:00 2001 From: Eureka Date: Tue, 10 Nov 2026 19:25:06 +0000 Subject: [PATCH] Persona: pin the schema a Direct session runs under; describe open_direct in the module doc Co-Authored-By: Claude Sonnet 5.5 --- crates/mind-body/src/persona.rs | 4 +++- crates/mind-body/src/persona/tests.rs | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/crates/mind-body/src/persona.rs b/crates/mind-body/src/persona.rs index ee9cc24..b139d64 100644 --- a/crates/mind-body/src/persona.rs +++ b/crates/mind-body/src/persona.rs @@ -28,7 +28,9 @@ //! `eureka-body:ruling:persona-reply-typed-by-schema`), decoded into that one type and acted on: //! each `say` is sent, each `remember` becomes a memory in her own mind and each `settle` //! closes an open commitment or ask there (ruling `eureka-body:ruling:persona-memory-written-not-transcript`), -//! with her vote in the same admission; `start_self_run` admits its brief as a follow-up and opens +//! with her vote in the same admission; `open_direct`, from a public session only, asks the mouth to open a +//! direct message with a person her session was shown, after the says and under the brakes read again: the mouth decides +//! from the chat's own room state, and a refusal or silence from it is told to her on her next line, never a failed step; `start_self_run` admits its brief as a follow-up and opens //! a Self run that claims it (ruling `eureka-body:ruling:self-run-brief-claimed-follow-up`), //! taking an open item on when it names one; and only then are the deliveries acked. A reply that //! cannot be decoded sends nothing, acks nothing and is told back to her with the refusal; the diff --git a/crates/mind-body/src/persona/tests.rs b/crates/mind-body/src/persona/tests.rs index 7a84bbe..e68d381 100644 --- a/crates/mind-body/src/persona/tests.rs +++ b/crates/mind-body/src/persona/tests.rs @@ -7857,3 +7857,15 @@ fn a_direct_session_that_opens_is_refused_and_nothing_is_opened() { assert_eq!(failure_of(rig.go()), Some(Failure::OutOfBounds(OPEN_DIRECT_FAULT))); assert!(rig.chat.opens.borrow().is_empty() && rig.chat.sent.borrow().is_empty() && rig.chat.acked.borrow().is_empty()); } + +#[test] +fn the_schema_a_session_runs_under_admits_an_open_only_in_a_public_session() { + let schema_of = |rig: &Rig| -> serde_json::Value { serde_json::from_str(&rig.model.requests.borrow()[0].output_schema_json).unwrap() }; + let public = public_rig(&[says(&[("swarm", "hi")])]); + assert_eq!(failure_of(public.go()), None); + assert_eq!(schema_of(&public)["properties"]["open_direct"]["anyOf"][0], json!({ "type": "null" })); + assert_eq!(schema_of(&public)["properties"]["open_direct"]["anyOf"][1]["required"], json!(["with", "text"])); + let private = Rig::new(vec![direct(1, "!dm:chat", "@ann:chat", "hi")], &[says(&[("!dm:chat", "hello")])]); + assert_eq!(failure_of(private.go()), None); + assert_eq!(schema_of(&private)["properties"]["open_direct"], json!({ "type": "null" })); +}