proto becomes bxcore, the one shared crate (M5b task 00)

Done the way the owner asked and the spike mapped: the crate and the
manifests renamed, then what the build reported fixed. Layers: 138
"proto unresolved" errors across 169 files; cargo fmt reordering
imports; six fixture paths built as strings in brokerd's and bxctl's
tests, which the compiler cannot see, and comments naming
crates/proto/; the crate-dependency check and its self-test. One more
the spike did not reach: a `\nproto =` key inside a printf format in
the self-test, which a word-boundary replacement skips because `n` and
`p` are both word characters.

make gate: gate: ok, 944 tests; no new entry in /tmp.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-26 01:48:38 -07:00
co-authored by Claude Opus 5.5
parent 727e027fcf
commit 2b3ae080b4
311 changed files with 426 additions and 410 deletions
+2 -2
View File
@@ -2,10 +2,10 @@
mod support;
use bxcore::{CallId, DataClass, Epoch, Hash32, LogRecord, SessionId, Timestamp, ToolCall};
use loopd::baseline::{Baseline, messages};
use loopd::llama::ChatMessage;
use loopd::tools::Registry;
use proto::{CallId, DataClass, Epoch, Hash32, LogRecord, SessionId, Timestamp, ToolCall};
use std::path::Path;
use support::Home;
@@ -67,7 +67,7 @@ fn json_round_trip_and_hash() {
assert_eq!(Baseline::from_json(&text).unwrap(), b);
assert_eq!(
b.hash().unwrap(),
proto::sha256(text.as_bytes()).unwrap(),
bxcore::sha256(text.as_bytes()).unwrap(),
"the hash is of the JSON as written"
);
assert_ne!(b.hash().unwrap(), Hash32::ZERO);
+4 -4
View File
@@ -9,12 +9,12 @@ use std::os::unix::net::UnixListener;
use std::thread;
use std::time::Duration;
use bxcore::{
DenyReason, Message, PROTOCOL_VERSION, Timestamp, ToolResponse, read_frame, write_frame,
};
use fake::{assert_unavailable, broker, call, frame, in_ms, request, result, send, socket_path};
use loopd::broker_port::{BrokerPort, NoBroker, POINTER, TOO_LARGE};
use loopd::tools::{Pending, ToolPort};
use proto::{
DenyReason, Message, PROTOCOL_VERSION, Timestamp, ToolResponse, read_frame, write_frame,
};
#[test]
fn a_result_comes_back_as_it_was_sent() {
@@ -259,7 +259,7 @@ fn a_request_too_large_for_a_frame_is_its_own_failure() {
let _ = std::fs::remove_file(&path);
let _listener = UnixListener::bind(&path).unwrap();
let mut big = request();
big.arguments = format!(r#"{{"path":"/{}"}}"#, "a".repeat(proto::MAX_FRAME));
big.arguments = format!(r#"{{"path":"/{}"}}"#, "a".repeat(bxcore::MAX_FRAME));
let got = call(path.to_path_buf(), 1_000, &big);
assert_eq!(
got.response,
+3 -1
View File
@@ -9,8 +9,10 @@ use std::os::unix::net::UnixStream;
use std::thread;
use std::time::Duration;
use bxcore::{
Envelope, ErrorCode, Message, PROTOCOL_VERSION, ToolResponse, WireError, write_frame,
};
use fake::{assert_unavailable, broker, call, frame, in_ms, request, result, send};
use proto::{Envelope, ErrorCode, Message, PROTOCOL_VERSION, ToolResponse, WireError, write_frame};
#[test]
fn frames_that_break_the_protocol_are_unavailable() {
+1 -1
View File
@@ -9,10 +9,10 @@ use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};
use bxcore::{Timestamp, ToolResponse};
use fake::{broker, request, send};
use loopd::broker_port::{BrokerPort, MAX_PENDING_WAIT, UNAVAILABLE};
use loopd::tools::ToolPort;
use proto::{Timestamp, ToolResponse};
#[test]
fn the_default_cap_is_a_day() {
+11 -11
View File
@@ -5,14 +5,14 @@
mod support;
use bxcore::{
Envelope, ErrorCode, Message, PROTOCOL_VERSION, SessionId, Turn, TurnEvent, read_frame,
write_frame,
};
use loopd::channel::{Context, serve};
use loopd::llama::Client;
use loopd::memory::NoMemory;
use loopd::tools::Registry;
use proto::{
Envelope, ErrorCode, Message, PROTOCOL_VERSION, SessionId, Turn, TurnEvent, read_frame,
write_frame,
};
use std::os::unix::net::{UnixListener, UnixStream};
use std::path::PathBuf;
use std::sync::Arc;
@@ -30,7 +30,7 @@ struct Loopd {
home: Home,
}
fn start(replies: Vec<proto::ToolResponse>) -> Loopd {
fn start(replies: Vec<bxcore::ToolResponse>) -> Loopd {
let home = Home::new();
let server = FakeServer::start();
let cfg = home.config(&server.socket);
@@ -177,7 +177,7 @@ fn tool_calls_are_reported_by_name_only() {
tool_events[1],
&TurnEvent::ToolResult {
name: "read_file".to_string(),
class: proto::DataClass::Private,
class: bxcore::DataClass::Private,
truncated: false
}
);
@@ -292,7 +292,7 @@ fn bad_frames_get_an_error_and_a_close() {
stream
.set_read_timeout(Some(Duration::from_secs(5)))
.unwrap();
let msg = Message::Error(proto::WireError {
let msg = Message::Error(bxcore::WireError {
code: ErrorCode::Internal,
detail: String::new(),
});
@@ -311,7 +311,7 @@ fn bad_frames_get_an_error_and_a_close() {
assert!(
matches!(
reply.msg,
Message::Error(proto::WireError {
Message::Error(bxcore::WireError {
code: ErrorCode::BadMessage,
..
})
@@ -319,7 +319,7 @@ fn bad_frames_get_an_error_and_a_close() {
"{reply:?}"
);
assert!(
matches!(read_frame(&mut stream), Err(proto::FrameError::Closed)),
matches!(read_frame(&mut stream), Err(bxcore::FrameError::Closed)),
"then the connection is closed"
);
@@ -333,7 +333,7 @@ fn bad_frames_get_an_error_and_a_close() {
assert!(
matches!(
reply.msg,
Message::Error(proto::WireError {
Message::Error(bxcore::WireError {
code: ErrorCode::BadMessage,
..
})
@@ -365,7 +365,7 @@ fn bad_frames_get_an_error_and_a_close() {
assert!(
matches!(
reply.msg,
Message::Error(proto::WireError {
Message::Error(bxcore::WireError {
code: ErrorCode::BadVersion,
..
})
+7 -7
View File
@@ -339,7 +339,7 @@ impl Served {
.to_string()
}
fn records(&self, session: &str) -> Vec<proto::LogRecord> {
fn records(&self, session: &str) -> Vec<bxcore::LogRecord> {
let text =
std::fs::read_to_string(self.home.join("sessions").join(session).join("0.jsonl"))
.unwrap();
@@ -441,7 +441,7 @@ fn a_conversation_uses_tools_survives_a_restart_and_keeps_its_cache() {
let tool_names: Vec<String> = records
.iter()
.filter_map(|r| match r {
proto::LogRecord::Assistant { tool_calls, .. } => Some(
bxcore::LogRecord::Assistant { tool_calls, .. } => Some(
tool_calls
.iter()
.map(|c| c.name.clone())
@@ -459,16 +459,16 @@ fn a_conversation_uses_tools_survives_a_restart_and_keeps_its_cache() {
);
let usages = records
.iter()
.filter(|r| matches!(r, proto::LogRecord::Usage { .. }))
.filter(|r| matches!(r, bxcore::LogRecord::Usage { .. }))
.count();
let assistants = records
.iter()
.filter(|r| matches!(r, proto::LogRecord::Assistant { .. }))
.filter(|r| matches!(r, bxcore::LogRecord::Assistant { .. }))
.count();
assert_eq!(usages, assistants, "one usage record per completion");
let losses: Vec<&proto::LogRecord> = records
let losses: Vec<&bxcore::LogRecord> = records
.iter()
.filter(|r| matches!(r, proto::LogRecord::CacheLoss { .. }))
.filter(|r| matches!(r, bxcore::LogRecord::CacheLoss { .. }))
.collect();
assert!(
losses.is_empty(),
@@ -476,7 +476,7 @@ fn a_conversation_uses_tools_survives_a_restart_and_keeps_its_cache() {
);
let results = records
.iter()
.filter(|r| matches!(r, proto::LogRecord::ToolResult { .. }))
.filter(|r| matches!(r, bxcore::LogRecord::ToolResult { .. }))
.count();
assert!(
results >= 3,
+3 -3
View File
@@ -12,15 +12,15 @@ use std::path::{Path, PathBuf};
use std::process::{Child, Command, Stdio};
use std::time::{Duration, Instant};
use bxcore::{
AuditEvent, AuditRecord, ChainVerifier, DecisionRecord, DenyReason, SessionId, TurnEvent,
};
use loopd::baseline::Baseline;
use loopd::broker_port::BrokerPort;
use loopd::llama::Client;
use loopd::session::Session;
use loopd::tools::Registry;
use loopd::turn::{Runtime, run_turn};
use proto::{
AuditEvent, AuditRecord, ChainVerifier, DecisionRecord, DenyReason, SessionId, TurnEvent,
};
use support::{FakeServer, Home, Reply};
const CHAT: &str = "/v1/chat/completions";
+1 -1
View File
@@ -56,7 +56,7 @@ fn reads_a_recorded_chunked_response() {
// The hash recorded in docs/inference-contract.md. If the de-chunking were off by a byte,
// this would not match.
assert_eq!(
proto::sha256(template.as_bytes()).unwrap().to_hex(),
bxcore::sha256(template.as_bytes()).unwrap().to_hex(),
"f55f52930aa8bf44ab5cb85f99370fcc3c56e9a85640b812086d5330bce5d86b"
);
}
+1 -1
View File
@@ -30,7 +30,7 @@ fn props_slots_and_tokenize_read_the_recorded_responses() {
assert_eq!(props.n_ctx, 131_072);
assert_eq!(props.total_slots, 2);
assert_eq!(
proto::sha256(props.chat_template.as_bytes())
bxcore::sha256(props.chat_template.as_bytes())
.unwrap()
.to_hex(),
"f55f52930aa8bf44ab5cb85f99370fcc3c56e9a85640b812086d5330bce5d86b"
+1 -1
View File
@@ -5,9 +5,9 @@ mod support;
#[path = "support/turn.rs"]
mod turn_support;
use bxcore::{LogRecord, SessionId, TurnEvent};
use loopd::session::Session;
use loopd::turn::TurnError;
use proto::{LogRecord, SessionId, TurnEvent};
use support::{Reply, ScriptedPort, ok_result};
use turn_support::{setup, types, without_cache_loss};
+3 -3
View File
@@ -9,13 +9,13 @@ use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use bxcore::{
Envelope, ErrorCode, Message, PROTOCOL_VERSION, SessionId, Turn, read_frame, write_frame,
};
use loopd::channel::{Context, serve};
use loopd::llama::Client;
use loopd::memory::{MemorySource, UNAVAILABLE};
use loopd::tools::Registry;
use proto::{
Envelope, ErrorCode, Message, PROTOCOL_VERSION, SessionId, Turn, read_frame, write_frame,
};
use support::{FakeServer, Home, Reply, ScriptedPort};
const CHAT: &str = "/v1/chat/completions";
+6 -6
View File
@@ -8,12 +8,12 @@ use std::path::Path;
use std::process::{Child, Command, Stdio};
use std::time::Duration;
use bxcore::SessionId;
use loopd::baseline::Baseline;
use loopd::broker_port::{not_configured_line, unavailable_line};
use loopd::memory::{MemoryPort, MemorySource};
use loopd::session::{Session, SessionError};
use loopd::tools::Registry;
use proto::SessionId;
use support::{FakeServer, Home, Reply};
// `want` is the whole pointer, written out: scripts/check-runbook.sh reads the anchors of every
@@ -78,17 +78,17 @@ fn memoryd_unreachable_or_refusing_names_the_memory_entry() {
let listener = std::os::unix::net::UnixListener::bind(&socket).unwrap();
std::thread::spawn(move || {
let (mut stream, _) = listener.accept().unwrap();
let env = proto::read_frame(&mut stream).unwrap();
let reply = proto::Envelope {
let env = bxcore::read_frame(&mut stream).unwrap();
let reply = bxcore::Envelope {
v: 1,
id: env.id,
r#final: true,
msg: proto::Message::Error(proto::WireError {
code: proto::ErrorCode::Internal,
msg: bxcore::Message::Error(bxcore::WireError {
code: bxcore::ErrorCode::Internal,
detail: "memory/user.md: 1,376 characters; its limit is 1,375".to_string(),
}),
};
proto::write_frame(&mut stream, &reply).unwrap();
bxcore::write_frame(&mut stream, &reply).unwrap();
});
let message = MemoryPort::new(socket, Duration::from_secs(5))
.block()
+1 -1
View File
@@ -83,7 +83,7 @@ fn thinking_off_and_tools() {
/// here on purpose: they are rendered differently.
#[test]
fn every_kind_of_message() {
let call = proto::ToolCall {
let call = bxcore::ToolCall {
id: "call_1".to_string(),
name: "read_file".to_string(),
arguments: r#"{"path":"/etc/hostname"}"#.to_string(),
+2 -2
View File
@@ -84,10 +84,10 @@ fn the_main_slot_comes_from_the_config() {
#[test]
fn each_expected_value_is_checked() {
let zero = proto::Hash32::ZERO;
let zero = bxcore::Hash32::ZERO;
let cases: [(&str, Edit); 3] = [
("chat template sha256", |c| {
c.expect.template_sha256 = proto::Hash32::ZERO
c.expect.template_sha256 = bxcore::Hash32::ZERO
}),
("context per slot", |c| c.expect.n_ctx = 4096),
("slot count", |c| c.expect.slots = 3),
+1 -1
View File
@@ -2,9 +2,9 @@
mod support;
use bxcore::{CallId, DataClass, Epoch, LogRecord, SessionId, Timestamp};
use loopd::baseline::Baseline;
use loopd::session::{Session, SessionError};
use proto::{CallId, DataClass, Epoch, LogRecord, SessionId, Timestamp};
use support::Home;
fn baseline() -> Baseline {
+3 -3
View File
@@ -12,12 +12,12 @@ use std::sync::{Arc, Mutex};
use std::thread::{self, JoinHandle};
use std::time::{Duration, Instant};
use loopd::broker_port::{BrokerPort, UNAVAILABLE};
use loopd::tools::{Pending, ToolPort};
use proto::{
use bxcore::{
CallId, DataClass, Envelope, Message, PROTOCOL_VERSION, SessionId, Timestamp, ToolRequest,
ToolResponse, read_frame, write_frame,
};
use loopd::broker_port::{BrokerPort, UNAVAILABLE};
use loopd::tools::{Pending, ToolPort};
static NEXT: AtomicU32 = AtomicU32::new(0);
+16 -16
View File
@@ -94,7 +94,7 @@ impl Home {
}
/// The records of a session's log, epoch 0.
pub fn records(&self, session: &str) -> Vec<proto::LogRecord> {
pub fn records(&self, session: &str) -> Vec<bxcore::LogRecord> {
let text = self.read(&format!("sessions/{session}/0.jsonl"));
text.lines()
.map(|l| serde_json::from_str(l).unwrap())
@@ -104,37 +104,37 @@ impl Home {
/// A tool port that answers from a script and records what it was asked.
pub struct ScriptedPort {
replies: Mutex<VecDeque<proto::ToolResponse>>,
calls: Mutex<Vec<proto::ToolRequest>>,
replies: Mutex<VecDeque<bxcore::ToolResponse>>,
calls: Mutex<Vec<bxcore::ToolRequest>>,
}
impl ScriptedPort {
/// Replies are given in order; when they run out, every call gets `fallback`.
pub fn new(replies: Vec<proto::ToolResponse>) -> ScriptedPort {
pub fn new(replies: Vec<bxcore::ToolResponse>) -> ScriptedPort {
ScriptedPort {
replies: Mutex::new(replies.into()),
calls: Mutex::new(Vec::new()),
}
}
pub fn calls(&self) -> Vec<proto::ToolRequest> {
pub fn calls(&self) -> Vec<bxcore::ToolRequest> {
self.calls.lock().unwrap().clone()
}
}
pub fn ok_result(content: &str) -> proto::ToolResponse {
proto::ToolResponse::Result {
pub fn ok_result(content: &str) -> bxcore::ToolResponse {
bxcore::ToolResponse::Result {
content: content.to_string(),
class: proto::DataClass::Private,
class: bxcore::DataClass::Private,
untrusted: true,
truncated: false,
}
}
pub fn pending(approval: u64, expires: &str) -> proto::ToolResponse {
proto::ToolResponse::PendingApproval {
pub fn pending(approval: u64, expires: &str) -> bxcore::ToolResponse {
bxcore::ToolResponse::PendingApproval {
approval,
expires: proto::Timestamp::parse(expires).unwrap(),
expires: bxcore::Timestamp::parse(expires).unwrap(),
}
}
@@ -144,13 +144,13 @@ impl loopd::tools::ToolPort for ScriptedPort {
/// `ReturnsPendingPort` for a port that breaks the rule and returns one.
fn call(
&self,
request: &proto::ToolRequest,
request: &bxcore::ToolRequest,
on_pending: &mut dyn FnMut(&loopd::tools::Pending),
) -> proto::ToolResponse {
) -> bxcore::ToolResponse {
self.calls.lock().unwrap().push(request.clone());
let mut replies = self.replies.lock().unwrap();
let mut reply = replies.pop_front();
if let Some(proto::ToolResponse::PendingApproval { approval, expires }) = reply {
if let Some(bxcore::ToolResponse::PendingApproval { approval, expires }) = reply {
on_pending(&loopd::tools::Pending { approval, expires });
reply = replies.pop_front();
}
@@ -164,9 +164,9 @@ pub struct ReturnsPendingPort;
impl loopd::tools::ToolPort for ReturnsPendingPort {
fn call(
&self,
_request: &proto::ToolRequest,
_request: &bxcore::ToolRequest,
_on_pending: &mut dyn FnMut(&loopd::tools::Pending),
) -> proto::ToolResponse {
) -> bxcore::ToolResponse {
pending(1, "2026-09-18T12:00:00.000Z")
}
}
+1 -1
View File
@@ -5,12 +5,12 @@
#![allow(dead_code)]
use crate::support::{FakeServer, Home, ScriptedPort};
use bxcore::{LogRecord, SessionId, ToolResponse, TurnEvent};
use loopd::baseline::Baseline;
use loopd::llama::Client;
use loopd::session::Session;
use loopd::tools::Registry;
use loopd::turn::{Runtime, TurnError, run_turn};
use proto::{LogRecord, SessionId, ToolResponse, TurnEvent};
pub struct Setup {
pub home: Home,
+4 -4
View File
@@ -3,10 +3,10 @@
mod support;
use bxcore::{CallId, DenyReason, SessionId, ToolRequest, ToolResponse};
use loopd::tools::{
Dispatch, FakeTools, Pending, Registry, ToolPort, cap_result, denial_text, dispatch,
};
use proto::{CallId, DenyReason, SessionId, ToolRequest, ToolResponse};
fn req(tool: &str, arguments: &str) -> ToolRequest {
ToolRequest {
@@ -125,10 +125,10 @@ fn any_other_tool_goes_to_the_port_as_it_is() {
fn the_clock_is_answered_locally_whatever_its_arguments() {
for registry in [Registry::m2b(), Registry::m3a(), Registry::new(vec![])] {
for arguments in ["{}", r#"{"zone":"UTC"}"#, "not json", ""] {
let before = proto::Timestamp::now();
let before = bxcore::Timestamp::now();
match dispatch(&registry, "clock", arguments) {
Dispatch::Local(text) => {
let time = proto::Timestamp::parse(&text)
let time = bxcore::Timestamp::parse(&text)
.unwrap_or_else(|e| panic!("an RFC 3339 time, got {text:?}: {e:?}"));
assert!(time >= before, "{text}");
assert!(text.ends_with('Z'), "UTC: {text}");
@@ -283,7 +283,7 @@ fn fake_tools_answer_echo_deny_the_rest_and_record_calls() {
truncated,
} => {
assert_eq!(content, "box");
assert_eq!(class, proto::DataClass::Public);
assert_eq!(class, bxcore::DataClass::Public);
assert!(!untrusted && !truncated);
}
other => panic!("{other:?}"),
+3 -3
View File
@@ -6,8 +6,8 @@ mod support;
#[path = "support/turn.rs"]
mod turn_support;
use bxcore::{DataClass, LogRecord, SessionId, ToolResponse, TurnEvent};
use loopd::tools::Registry;
use proto::{DataClass, LogRecord, SessionId, ToolResponse, TurnEvent};
use support::{Reply, ok_result};
use turn_support::{setup, types};
@@ -102,7 +102,7 @@ fn a_tool_turn_goes_through_the_port_and_records_everything() {
"arguments are passed on unparsed"
);
assert_eq!(calls[0].session, SessionId::new("a").unwrap());
assert_eq!(calls[0].call, proto::CallId(1));
assert_eq!(calls[0].call, bxcore::CallId(1));
match &session.records()[4] {
LogRecord::ToolResult {
@@ -114,7 +114,7 @@ fn a_tool_turn_goes_through_the_port_and_records_everything() {
truncated,
..
} => {
assert_eq!(*call, proto::CallId(1));
assert_eq!(*call, bxcore::CallId(1));
assert_eq!(
tool_call_id, "wgE8iFI58Zni4WCTiCMNp4TzCcM8ou7F",
"the server's id, so the template can pair it"
+1 -1
View File
@@ -5,7 +5,7 @@ mod support;
#[path = "support/turn.rs"]
mod turn_support;
use proto::{DataClass, DenyReason, LogRecord, Timestamp, ToolResponse, TurnEvent};
use bxcore::{DataClass, DenyReason, LogRecord, Timestamp, ToolResponse, TurnEvent};
use support::{Reply, ReturnsPendingPort, ok_result, pending};
use turn_support::{setup, types};