Show a message another agent sent, on a session this server is running

Peer messages were only ever produced by the *import* path, reading them out
of the CLI's own session file. A message another agent sent to a session
this server was driving appeared nowhere, so the session started working on
something nobody on the phone had asked for and there was nothing on screen
to explain it.

Measured rather than guessed, because the obvious place to look for it is
empty: a real cross-session message sent to a real `--input-format
stream-json` session on CLI 2.1.237 produces **no `user` record**, and
nothing in the partial-message stream mentions it either. The whole of it
arrives as an `origin` object on the turn's `result`, in exactly the shape
the session file records -- so `import::peer_message` now reads both, one
function for one wire format. Two copies would drift the first time a field
is renamed, and the half that drifted would go on producing nothing, which
is indistinguishable from nobody having sent anything.

The cost is the position: the note lands after the reply it caused rather
than above it, because at no earlier point in the turn does the CLI say why
the turn started. Taken deliberately over the alternative -- a second reader
tailing the CLI's own session file for the one record stdout does not carry,
which is two sources of truth for one conversation and a poll per live
session. Recorded in PLAN.md so that if the CLI ever announces the injection
where it happens, the next reader knows to move it there.

Both halves tested: the real record shape, and an ordinary result carrying
no `origin` -- which is the half that decides whether the check is a check.
Four ordinary results on a real session's stdout had none between them.
This commit is contained in:
iris committed 2026-08-31 23:02:49 -04:00
1 parent fe6a36bde4
commit 6236f0d5bd
4 files changed
+132 -2

No files matched your search

+9 -2
View File
@@ -520,7 +520,7 @@ pub fn events_from(text: &str, session_dir: &std::path::Path) -> Vec<Event> {
events
}
/// A message from another agent, as the CLI records one.
/// A message from another agent, as the CLI reports one.
///
/// Measured from a real session file (2026-08-29): the record is a `user`
/// one marked `isMeta`, and its `origin` carries `kind: "peer"`, the
@@ -529,7 +529,14 @@ pub fn events_from(text: &str, session_dir: &std::path::Path) -> Vec<Event> {
/// preamble and a `<cross-session-message>` tag, which is written for the
/// model that has to read it rather than for a person -- so the body is
/// what a reader is shown, and the name is who they are told sent it.
fn peer_message(record: &Value) -> Option<Event> {
///
/// Shared with the live driver (`claude::translate`), which finds the same
/// `origin` object on a different record -- so this reads the object and
/// not the record around it. One function because it is one wire format:
/// two copies would drift the first time the CLI renames a field, and the
/// half that drifted would go on producing nothing at all, which is
/// indistinguishable from nobody having sent anything.
pub(in crate::session) fn peer_message(record: &Value) -> Option<Event> {
let origin = record.get("origin")?;
if origin.get("kind").and_then(Value::as_str) != Some("peer") {
return None;