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
+1 -1
View File
@@ -9,5 +9,5 @@ publish.workspace = true
workspace = true
[dependencies]
proto.workspace = true
bxcore.workspace = true
serde_json.workspace = true
+5 -5
View File
@@ -4,7 +4,7 @@ use std::io::{self, Write};
use std::os::unix::net::UnixStream;
use std::path::{Path, PathBuf};
use proto::{
use bxcore::{
Approve, DecisionRecord, DenyReason, Empty, Envelope, ErrorCode, FrameError, Message,
PROTOCOL_VERSION, PendingApproval, Refuse, Timestamp, WireError, read_frame, write_frame,
};
@@ -288,10 +288,10 @@ fn session_shown(session: &str) -> String {
}
// The taint of a decision is its wire name.
fn taint_name(taint: proto::DataClass) -> &'static str {
fn taint_name(taint: bxcore::DataClass) -> &'static str {
match taint {
proto::DataClass::Public => "public",
proto::DataClass::Private => "private",
proto::DataClass::Secret => "secret",
bxcore::DataClass::Public => "public",
bxcore::DataClass::Private => "private",
bxcore::DataClass::Secret => "secret",
}
}
+2 -2
View File
@@ -4,7 +4,7 @@ use std::io::{BufRead, Write};
use std::os::unix::net::UnixStream;
use std::path::Path;
use proto::{
use bxcore::{
DenyReason, Envelope, ErrorCode, Message, PROTOCOL_VERSION, SessionId, Timestamp, Turn,
TurnDone, TurnEvent, WireError, read_frame, write_frame,
};
@@ -15,7 +15,7 @@ use crate::escape::{escape_json_text, escape_model_text};
#[derive(Debug)]
pub enum ChatError {
Connect(std::io::Error),
Frame(proto::FrameError),
Frame(bxcore::FrameError),
Refused(WireError),
Protocol(String),
}
+1 -1
View File
@@ -2,7 +2,7 @@
use std::path::{Path, PathBuf};
use proto::SessionId;
use bxcore::SessionId;
// Shown on stderr for any usage error. It names every subcommand and the flags they share, so a
// single line tells the owner what they can type.
+2 -2
View File
@@ -1,3 +1,3 @@
//! The text-escape helpers, from `proto` (moved there in M4b so `gatewayd` shows the same thing).
//! The text-escape helpers, from `bxcore` (moved there in M4b so `gatewayd` shows the same thing).
pub use proto::escape::{escape_json_text, escape_model_text};
pub use bxcore::escape::{escape_json_text, escape_model_text};
+1 -1
View File
@@ -4,11 +4,11 @@ use std::io::{BufRead, BufReader, Write};
use std::path::{Path, PathBuf};
use std::process::ExitCode;
use bxcore::{ErrorCode, SessionId, Timestamp, TurnDone};
use bxctl::admin::{self, AdminError};
use bxctl::chat::{Approvals, ChatError, OnPending, Printer, TurnIo, new_session_id, stream_turn};
use bxctl::cli::{self, ChatOptions, Command, USAGE};
use bxctl::escape::escape_model_text;
use proto::{ErrorCode, SessionId, Timestamp, TurnDone};
fn main() -> ExitCode {
// `args_os`, because `args` panics on an argument that is not UTF-8. bxctl's arguments are
+1 -1
View File
@@ -6,7 +6,7 @@ use std::os::unix::net::UnixStream;
use std::path::{Path, PathBuf};
use std::time::Duration;
use proto::{
use bxcore::{
Empty, Envelope, MemoryAdmin, MemoryCommand, Message, PROTOCOL_VERSION, read_frame, write_frame,
};
+3 -3
View File
@@ -1,10 +1,10 @@
//! Verifies the whole audit log under a home directory with `proto::ChainVerifier`, reading the
//! Verifies the whole audit log under a home directory with `bxcore::ChainVerifier`, reading the
//! files itself so it works when `brokerd` will not start.
use std::io::Write;
use std::path::Path;
use proto::ChainVerifier;
use bxcore::ChainVerifier;
/// Verifies the whole audit log under `home` and prints the report to `out`.
/// `Ok(true)`: the chain verifies. `Ok(false)`: it does not. `Err`: the log cannot be read.
@@ -21,7 +21,7 @@ pub fn run(home: &Path, out: &mut dyn Write) -> std::io::Result<bool> {
continue;
}
};
if proto::is_audit_log_name(&name) {
if bxcore::is_audit_log_name(&name) {
names.push(name);
} else if name.ends_with(".jsonl") {
// Looks like a log file but is not named as one: brokerd ignores it too. Say so, so
+7 -7
View File
@@ -3,14 +3,14 @@
mod support;
use bxcore::{
Approve, DecisionRecord, DenyReason, Empty, Envelope, ErrorCode, GrantProblem, GrantsReport,
Message, PROTOCOL_VERSION, Refuse,
};
use bxctl::admin::{
AdminError, cmd_approvals, cmd_approve, cmd_grants_check, cmd_refuse, list, reason_name,
request, write_block,
};
use proto::{
Approve, DecisionRecord, DenyReason, Empty, Envelope, ErrorCode, GrantProblem, GrantsReport,
Message, PROTOCOL_VERSION, Refuse,
};
use std::process::Command;
use support::{brokerd_with, fake_brokerd, fake_brokerd_frames, pending, ts, wire_error};
@@ -140,7 +140,7 @@ fn reason_names_are_the_wire_names() {
// ---- the block ----
fn block(item: &proto::PendingApproval, now: &str) -> String {
fn block(item: &bxcore::PendingApproval, now: &str) -> String {
let mut out = Vec::new();
write_block(&mut out, item, ts(now)).unwrap();
text(out)
@@ -190,7 +190,7 @@ fn a_session_id_longer_than_ten_characters_is_cut_to_nine_and_an_ellipsis() {
("abcdefghij", "session abcdefghij "),
("abcdefghijk", "session abcdefghi… "),
] {
item.session = proto::SessionId::new(id).unwrap();
item.session = bxcore::SessionId::new(id).unwrap();
let got = block(&item, "2026-09-18T12:00:00.000Z");
assert!(got.contains(shown), "{id}: {got}");
}
@@ -199,7 +199,7 @@ fn a_session_id_longer_than_ten_characters_is_cut_to_nine_and_an_ellipsis() {
#[test]
fn taint_is_the_wire_name() {
let mut item = pending(41, "shell", "{}");
item.taint = proto::DataClass::Secret;
item.taint = bxcore::DataClass::Secret;
assert!(block(&item, "2026-09-18T12:00:00.000Z").contains(" taint secret\n"));
}
+1 -1
View File
@@ -5,8 +5,8 @@ mod temp;
use std::os::unix::net::UnixListener;
use std::time::{Duration, Instant};
use bxcore::{Empty, Message};
use bxctl::admin::{ADMIN_TIMEOUT, request_with_timeout};
use proto::{Empty, Message};
#[test]
fn the_default_is_thirty_seconds() {
+2 -2
View File
@@ -2,11 +2,11 @@
#[path = "support/temp.rs"]
mod temp;
use bxctl::chat::{ChatError, Printer, new_session_id, run_turn};
use proto::{
use bxcore::{
DataClass, Envelope, ErrorCode, Message, PROTOCOL_VERSION, SessionId, Turn, TurnDone,
TurnEvent, Usage, WireError, read_frame, write_frame,
};
use bxctl::chat::{ChatError, Printer, new_session_id, run_turn};
use std::os::unix::net::UnixListener;
use std::path::PathBuf;
use std::process::Command;
+4 -4
View File
@@ -5,10 +5,10 @@
mod support;
use bxctl::chat::{Approvals, OnPending, Printer, TurnIo, handle_pending, stream_turn};
use proto::{
use bxcore::{
Approve, DecisionRecord, Empty, ErrorCode, Message, Refuse, SessionId, Timestamp, TurnEvent,
};
use bxctl::chat::{Approvals, OnPending, Printer, TurnIo, handle_pending, stream_turn};
use std::io::{BufRead, Cursor, Write};
use std::path::Path;
use std::process::{Command, Stdio};
@@ -178,7 +178,7 @@ fn a_brokerd_that_cannot_be_reached_is_reported_and_nothing_is_asked() {
#[test]
fn an_answer_that_comes_too_late_is_reported() {
let fake = fake_brokerd(|msg| match msg {
Message::Approvals(_) => Message::ApprovalList(proto::ApprovalList {
Message::Approvals(_) => Message::ApprovalList(bxcore::ApprovalList {
items: vec![pending(41, "shell", "{}")],
}),
_ => wire_error(ErrorCode::NoSuchApproval, "no such approval"),
@@ -204,7 +204,7 @@ fn an_answer_that_comes_too_late_is_reported() {
#[test]
fn an_answer_that_fails_is_reported_and_is_not_an_error() {
let fake = fake_brokerd(|msg| match msg {
Message::Approvals(_) => Message::ApprovalList(proto::ApprovalList {
Message::Approvals(_) => Message::ApprovalList(bxcore::ApprovalList {
items: vec![pending(41, "shell", "{}")],
}),
_ => wire_error(ErrorCode::Internal, "boom"),
+1 -1
View File
@@ -1,7 +1,7 @@
//! Tests for how `bxctl chat` prints what the model wrote and what `brokerd` denied. Do not edit.
use bxcore::{DataClass, DenyReason, Timestamp, TurnEvent};
use bxctl::chat::Printer;
use proto::{DataClass, DenyReason, Timestamp, TurnEvent};
const BACKSLASH: char = '\\';
+1 -1
View File
@@ -1,7 +1,7 @@
//! Tests for `bxctl`'s command line. Do not edit.
use bxcore::SessionId;
use bxctl::cli::{ChatOptions, Command, USAGE, UsageError, parse};
use proto::SessionId;
use std::path::{Path, PathBuf};
use std::process::Command as Process;
+3 -3
View File
@@ -8,12 +8,12 @@ use std::path::{Path, PathBuf};
use std::sync::mpsc;
use std::time::Duration;
use bxctl::cli::{Command, UsageError, parse};
use bxctl::memory::{Ask, run};
use proto::{
use bxcore::{
Envelope, ErrorCode, MemoryAdminReply, MemoryCommand, Message, Reindexed, WireError,
read_frame, write_frame,
};
use bxctl::cli::{Command, UsageError, parse};
use bxctl::memory::{Ask, run};
fn args(line: &str) -> Vec<String> {
line.split_whitespace().map(str::to_string).collect()
+5 -5
View File
@@ -1,9 +1,9 @@
//! Text from `brokerd` or the inference server is escaped like model text before it reaches the
//! terminal: a `retrying` error and every error detail (M3a review finding 10).
use bxcore::{ErrorCode, TurnEvent, WireError};
use bxctl::admin::AdminError;
use bxctl::chat::{ChatError, Printer};
use proto::{ErrorCode, TurnEvent, WireError};
const ESC: char = '\u{1b}';
@@ -61,13 +61,13 @@ fn an_error_detail_is_escaped_in_chat_and_admin_errors() {
#[test]
fn a_frame_error_is_escaped() {
let bad = r#"{"v":1,"id":1,"final":true,"msg":{"kind":"\u001b[2J\u202e"}}"#;
let error = serde_json::from_str::<proto::Envelope>(bad).unwrap_err();
let error = serde_json::from_str::<bxcore::Envelope>(bad).unwrap_err();
for text in [
ChatError::Frame(proto::FrameError::Json(
serde_json::from_str::<proto::Envelope>(bad).unwrap_err(),
ChatError::Frame(bxcore::FrameError::Json(
serde_json::from_str::<bxcore::Envelope>(bad).unwrap_err(),
))
.to_string(),
AdminError::Frame(proto::FrameError::Json(error)).to_string(),
AdminError::Frame(bxcore::FrameError::Json(error)).to_string(),
] {
clean(&text);
assert!(text.contains("\\u001b"), "{text}");
+4 -4
View File
@@ -2,7 +2,7 @@
#![allow(dead_code)] // each test file uses a different part of this module
use proto::{
use bxcore::{
ApprovalList, CallId, DataClass, Envelope, ErrorCode, Message, PROTOCOL_VERSION,
PendingApproval, SessionId, Timestamp, TurnDone, TurnEvent, Usage, WireError, read_frame,
write_frame,
@@ -128,7 +128,7 @@ pub fn pending(approval: u64, tool: &str, arguments: &str) -> PendingApproval {
/// A `brokerd` with these approvals pending. `approve` is answered with `outcome`, `refuse` with
/// `ok`; both answer `no_such_approval` for an id that is not in the list.
pub fn brokerd_with(items: Vec<PendingApproval>, outcome: proto::DecisionRecord) -> FakeBrokerd {
pub fn brokerd_with(items: Vec<PendingApproval>, outcome: bxcore::DecisionRecord) -> FakeBrokerd {
fake_brokerd(move |msg| {
let known = |id: u64| items.iter().any(|item| item.approval == id);
match msg {
@@ -136,11 +136,11 @@ pub fn brokerd_with(items: Vec<PendingApproval>, outcome: proto::DecisionRecord)
items: items.clone(),
}),
Message::Approve(a) if known(a.approval) => {
Message::ApproveResult(proto::ApproveResult {
Message::ApproveResult(bxcore::ApproveResult {
outcome: outcome.clone(),
})
}
Message::Refuse(r) if known(r.approval) => Message::Ok(proto::Empty {}),
Message::Refuse(r) if known(r.approval) => Message::Ok(bxcore::Empty {}),
Message::Approve(_) | Message::Refuse(_) => {
wire_error(ErrorCode::NoSuchApproval, "no such approval")
}
+4 -4
View File
@@ -1,4 +1,4 @@
//! `bxctl audit verify` against the fixture logs in `crates/proto/tests/fixtures/audit/`.
//! `bxctl audit verify` against the fixture logs in `crates/bxcore/tests/fixtures/audit/`.
//! Do not edit. The output is compared byte for byte: the owner reads it, and so do scripts.
use std::path::PathBuf;
@@ -20,7 +20,7 @@ impl Home {
let audit = path.join("audit");
std::fs::create_dir_all(&audit).unwrap();
let from = format!(
"{}/../proto/tests/fixtures/audit/{case}",
"{}/../bxcore/tests/fixtures/audit/{case}",
env!("CARGO_MANIFEST_DIR")
);
for entry in std::fs::read_dir(&from).unwrap_or_else(|e| panic!("{from}: {e}")) {
@@ -49,11 +49,11 @@ fn run(case: &str) -> (bool, String) {
/// The hex of the hash of the last line of `file` in `case`.
fn head_of(case: &str, file: &str) -> String {
let path = format!(
"{}/../proto/tests/fixtures/audit/{case}/{file}",
"{}/../bxcore/tests/fixtures/audit/{case}/{file}",
env!("CARGO_MANIFEST_DIR")
);
let text = std::fs::read_to_string(path).unwrap();
proto::sha256(text.lines().last().unwrap().as_bytes())
bxcore::sha256(text.lines().last().unwrap().as_bytes())
.unwrap()
.to_hex()
}
+1 -1
View File
@@ -9,7 +9,7 @@ fn home(tag: &str) -> temp::TempDir {
let dir = temp::TempDir::new(&format!("bx-verify-skip-{tag}"));
std::fs::create_dir_all(dir.join("audit")).unwrap();
let fixture =
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../proto/tests/fixtures/audit/good");
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../bxcore/tests/fixtures/audit/good");
for entry in std::fs::read_dir(fixture).unwrap() {
let entry = entry.unwrap();
std::fs::copy(entry.path(), dir.join("audit").join(entry.file_name())).unwrap();