diff --git a/adapters/mock/src/console_mode_probe.rs b/adapters/mock/src/console_mode_probe.rs index 0dd059e9..e2ee5510 100644 --- a/adapters/mock/src/console_mode_probe.rs +++ b/adapters/mock/src/console_mode_probe.rs @@ -124,7 +124,10 @@ fn go_raw() { use windows_sys::Win32::System::Console::{ ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT, }; - set_input_bits(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT, false); + set_input_bits( + ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT, + false, + ); } /// SEED the defect: turn cooked input back on, so a rig asserting it stays off diff --git a/adapters/mock/src/main.rs b/adapters/mock/src/main.rs index 4baf057b..94bf735b 100644 --- a/adapters/mock/src/main.rs +++ b/adapters/mock/src/main.rs @@ -210,7 +210,9 @@ fn main() { bind_args.push("--type".to_string()); bind_args.push(ty.clone()); } - breadcrumb(&format!("mode={mode} bind-start spt={spt} args={bind_args:?}")); + breadcrumb(&format!( + "mode={mode} bind-start spt={spt} args={bind_args:?}" + )); // CAPTURED, not inherited: this child's stderr is the ONLY place the // refusal sentence exists, and mock-session's own stderr is the PTY the // broker swallows when the session never registers. @@ -264,7 +266,9 @@ fn main() { bind_args.push("--type".to_string()); bind_args.push(ty.clone()); } - breadcrumb(&format!("mode=default bind-start spt={spt} args={bind_args:?}")); + breadcrumb(&format!( + "mode=default bind-start spt={spt} args={bind_args:?}" + )); let bind = Command::new(&spt).args(&bind_args).output(); breadcrumb(&format!("mode=default bind-done {}", bind_report(&bind))); if !matches!(&bind, Ok(o) if o.status.success()) { diff --git a/crates/spt-daemon/src/access.rs b/crates/spt-daemon/src/access.rs index 7936f1b3..b34d85b5 100644 --- a/crates/spt-daemon/src/access.rs +++ b/crates/spt-daemon/src/access.rs @@ -275,11 +275,11 @@ impl DiscoverGate { #[cfg(test)] mod tests { - use spt_store::access::REPLY_WINDOW_MS; - use spt_store::perch::node_key_file; use super::*; use crate::test_home::with_home; + use spt_store::access::REPLY_WINDOW_MS; use spt_store::access::{AccessRule, Mode, OriginQualifier, Provenance, RuleDecision, Subject}; + use spt_store::perch::node_key_file; // [unit->REQ-TRUST-WARNING] the whole warning table, over EVERY pass reason // in both classification states. Two properties are pinned at once: an @@ -558,7 +558,10 @@ mod tests { s.save().unwrap(); let gate = DiscoverGate::load(); - assert!(gate.discloses("ling", "aa11"), "the DISCOVER subject sees it"); + assert!( + gate.discloses("ling", "aa11"), + "the DISCOVER subject sees it" + ); assert!( gate.discloses("doyle", "bb22"), "the refusal is scoped to the ruled endpoint" @@ -776,7 +779,9 @@ mod tests { with_home(|_| { let mut s = AccessStore::default(); s.endpoint_mut("ling").rules.push(AccessRule { - subject: Subject::Node { node: "aa11".into() }, + subject: Subject::Node { + node: "aa11".into(), + }, surfaces: Vec::new(), origin: OriginQualifier::User, provenance: Provenance::Manual, @@ -875,11 +880,7 @@ mod tests { "a reply to the engine room's own outbound reaches it" ); assert_eq!( - classify_engine_room_inbound( - Posture::Online, - surface::MSG, - InboundClass::Unsolicited, - ), + classify_engine_room_inbound(Posture::Online, surface::MSG, InboundClass::Unsolicited,), InboundLock::Unsolicited, "and nothing else does" ); @@ -973,7 +974,14 @@ mod tests { // The wrapper and the stamped path agree — neither is the loose one. assert_eq!( access_check(er, &me, surface::MSG, InboundClass::Unsolicited), - access_check_with_sender(er, &me, surface::MSG, InboundClass::Unsolicited, None, None), + access_check_with_sender( + er, + &me, + surface::MSG, + InboundClass::Unsolicited, + None, + None + ), "the wrapper must not be a second, weaker gate" ); // And an ordinary endpoint still passes through the stamped path. @@ -1223,7 +1231,10 @@ mod tests { spt_store::info::set_controlled(&spt_store::engineroom::engine_room_perch(), false) .expect("detach"); let gate = DiscoverGate::load(); - assert!(!gate.discloses(er, "bb22"), "de-advertisement rides the posture drop"); + assert!( + !gate.discloses(er, "bb22"), + "de-advertisement rides the posture drop" + ); assert!(!gate.discloses(er, &me)); assert!( gate.discloses("ling", "bb22"), diff --git a/crates/spt-daemon/src/activity.rs b/crates/spt-daemon/src/activity.rs index 54bd438c..7fd04fbf 100644 --- a/crates/spt-daemon/src/activity.rs +++ b/crates/spt-daemon/src/activity.rs @@ -285,7 +285,10 @@ mod tests { #[test] fn a_state_change_owes_a_push_both_directions() { let mut seen = SeenLinks::new(); - remember(&mut seen, &[obs("doyle", "mock-shell-0", "tok-a", false, 900)]); + remember( + &mut seen, + &[obs("doyle", "mock-shell-0", "tok-a", false, 900)], + ); let to_idle = vec![obs("doyle", "mock-shell-0", "tok-a", true, 1_000)]; assert_eq!(plan_pushes(&seen, &to_idle), to_idle, "busy→idle pushes"); @@ -303,7 +306,10 @@ mod tests { #[test] fn a_token_change_with_an_identical_state_owes_a_push() { let mut seen = SeenLinks::new(); - remember(&mut seen, &[obs("doyle", "mock-shell-0", "tok-a", true, 1_000)]); + remember( + &mut seen, + &[obs("doyle", "mock-shell-0", "tok-a", true, 1_000)], + ); // Same owner, same shell, same state, same instant — only the link is new. let relinked = vec![obs("doyle", "mock-shell-0", "tok-b", true, 1_000)]; assert_eq!( @@ -326,7 +332,10 @@ mod tests { // The shell closed: this sweep observes nothing. remember(&mut seen, &[]); - assert!(seen.is_empty(), "a vanished link is forgotten, not accumulated"); + assert!( + seen.is_empty(), + "a vanished link is forgotten, not accumulated" + ); // It comes back on the SAME token and state — still a push (it is a new // link establishment from the consumer's side). @@ -385,8 +394,20 @@ mod tests { std::fs::write(owner_perch.join(spt_store::perch::IDLE_SENTINEL), "").unwrap(); perch::stamp_activity_at(&owner_perch, true, 1_753_372_800_123); - park_shell(&owlery, "doyle", "live-0", SHELL_STATUS_ONLINE, Some("tok-live")); - park_shell(&owlery, "doyle", "offline-0", SHELL_STATUS_OFFLINE, Some("tok-off")); + park_shell( + &owlery, + "doyle", + "live-0", + SHELL_STATUS_ONLINE, + Some("tok-live"), + ); + park_shell( + &owlery, + "doyle", + "offline-0", + SHELL_STATUS_OFFLINE, + Some("tok-off"), + ); park_shell(&owlery, "doyle", "tokenless-0", SHELL_STATUS_ONLINE, None); let observed = observe_links(&owlery); @@ -467,7 +488,10 @@ mod tests { // (identity/ may not exist on a fresh home). let marker = tmp.path().join("identity").join(FLIP_MARKER_FILE); - assert!(!take_flip_observation(&marker), "no marker ⇒ nothing to take"); + assert!( + !take_flip_observation(&marker), + "no marker ⇒ nothing to take" + ); request_flip_observation(&marker).expect("drop creates the parent dir"); request_flip_observation(&marker).expect("a second flip re-drops idempotently"); assert!(take_flip_observation(&marker), "the drop is taken"); diff --git a/crates/spt-daemon/src/answerop.rs b/crates/spt-daemon/src/answerop.rs index b195399a..8aa275d1 100644 --- a/crates/spt-daemon/src/answerop.rs +++ b/crates/spt-daemon/src/answerop.rs @@ -291,10 +291,7 @@ mod tests { .lookup("doyle") .map(|a| { a.rules.iter().any(|r| { - r.subject - == spt_store::access::Subject::SenderEndpoint { - id: "ling".into(), - } + r.subject == spt_store::access::Subject::SenderEndpoint { id: "ling".into() } }) }) .unwrap_or(false) @@ -487,7 +484,11 @@ mod tests { assert!(!reverse_rule_landed(), "and no reverse rule is written"); let row = only_notif(); - assert_eq!(row.to_id.as_deref(), Some("doyle"), "addressed to the knocker"); + assert_eq!( + row.to_id.as_deref(), + Some("doyle"), + "addressed to the knocker" + ); assert_eq!(row.from_id, "ling", "issued by the endpoint that approved"); assert_eq!(row.subnet, SUBNET, "filed under a real member subnet"); assert!( diff --git a/crates/spt-daemon/src/applyhost.rs b/crates/spt-daemon/src/applyhost.rs index 858cd28d..b0a48fd0 100644 --- a/crates/spt-daemon/src/applyhost.rs +++ b/crates/spt-daemon/src/applyhost.rs @@ -421,7 +421,9 @@ fn staged_already_applied( } } // This version (or newer) is already the promoted, running image. - applied_version.map(|a| a >= staged_version).unwrap_or(false) + applied_version + .map(|a| a >= staged_version) + .unwrap_or(false) } /// Where the outgoing binary steps aside: a sibling `.old-` @@ -580,9 +582,7 @@ mod tests { ) .expect("broker image pump brain"); let v = brain - .broker_image_version_until(Some( - std::time::Instant::now() + Duration::from_secs(2), - )) + .broker_image_version_until(Some(std::time::Instant::now() + Duration::from_secs(2))) .expect("broker image query round-trips before its deadline"); assert_eq!( v.as_deref(), @@ -704,7 +704,11 @@ mod tests { /// Sign a single release (sk = [9u8;32], matching `stage`) and write the /// matching release-keys.json — WITHOUT staging, so a test controls the /// platform stamp itself. - fn sign_single(dir: &Path, version: u64, artifact: &[u8]) -> (SignedRelease, std::path::PathBuf) { + fn sign_single( + dir: &Path, + version: u64, + artifact: &[u8], + ) -> (SignedRelease, std::path::PathBuf) { let sk = SigningKey::from_bytes(&[9u8; 32]); let meta = ReleaseMetadata { version, @@ -816,7 +820,10 @@ mod tests { // Wire the supervisor signal; the verb now raises it and reports honored. let signal = Arc::new(crate::brainproc::BrainRestart::new()); - assert!(broker.set_brain_restart(Arc::clone(&signal)), "first wire wins"); + assert!( + broker.set_brain_restart(Arc::clone(&signal)), + "first wire wins" + ); let mut b2 = cold_connect_retry(&name); assert!( b2.request_brain_restart().expect("verb round-trips"), @@ -847,7 +854,10 @@ mod tests { // Supervisor wired: refresh raises the same planned-restart signal the // apply path rides — with nothing staged anywhere. let signal = Arc::new(crate::brainproc::BrainRestart::new()); - assert!(broker.set_brain_restart(Arc::clone(&signal)), "first wire wins"); + assert!( + broker.set_brain_restart(Arc::clone(&signal)), + "first wire wins" + ); assert!( refresh_brain(&name).expect("refresh round-trips"), "a wired supervisor must report honored=true" @@ -939,7 +949,10 @@ mod tests { // No served_broker — deliberately. A daemonless apply must not need one. let out = apply_staged_daemonless(&cache, &keys, &exe).expect("apply ok"); assert!( - matches!(out, ApplyStagedOutcome::AppliedDaemonless { version: 7, .. }), + matches!( + out, + ApplyStagedOutcome::AppliedDaemonless { version: 7, .. } + ), "got {out:?}" ); assert_eq!( @@ -1161,7 +1174,10 @@ mod tests { .record_applied_state(&AppliedRecord::RolledBack { quarantine_version: 7, running_version: 6, - rollback_binary: exe.with_file_name("spt-binary.old-7").to_string_lossy().into(), + rollback_binary: exe + .with_file_name("spt-binary.old-7") + .to_string_lossy() + .into(), }) .unwrap(); @@ -1178,7 +1194,10 @@ mod tests { .record_applied_state(&AppliedRecord::RolledBack { quarantine_version: 7, running_version: 6, - rollback_binary: exe.with_file_name("spt-binary.old-7").to_string_lossy().into(), + rollback_binary: exe + .with_file_name("spt-binary.old-7") + .to_string_lossy() + .into(), }) .unwrap(); let out = apply_staged(&cache8, &keys8, &exe, &name).expect("ok"); diff --git a/crates/spt-daemon/src/attach.rs b/crates/spt-daemon/src/attach.rs index 6fb69a56..f8876a29 100644 --- a/crates/spt-daemon/src/attach.rs +++ b/crates/spt-daemon/src/attach.rs @@ -112,7 +112,7 @@ pub fn classify_rc_lock( } use crate::brain::{now_ms, Brain, BrokerEvent}; -use crate::effect::{Minter, MintedOp}; +use crate::effect::{MintedOp, Minter}; use crate::msg::{decode_bytes, encode_bytes}; /// Feed the resting-state machine at the attach edges (D9-2, REQ-INST-3): a @@ -875,7 +875,9 @@ pub fn request_attach( open_op: MintedOp, intent: AttachIntent, ) -> io::Result { - request_attach_endpoint(brain, conn_id, session_id, from_seq, open_op, intent, None, None, false) + request_attach_endpoint( + brain, conn_id, session_id, from_seq, open_op, intent, None, None, false, + ) } /// Like [`request_attach`], but for the cross-node leg (#4, diff --git a/crates/spt-daemon/src/attachment.rs b/crates/spt-daemon/src/attachment.rs index ca59b4c2..ee54aacd 100644 --- a/crates/spt-daemon/src/attachment.rs +++ b/crates/spt-daemon/src/attachment.rs @@ -507,7 +507,9 @@ pub fn run_observer(stop: &AtomicBool, source: &dyn Fn() -> HashMapREQ-ATTACH-LINK-PUSH] // [impl->REQ-SEAT-LIFETIME-BOUNDED] -pub fn spawn_attach_observer(broker: Arc) -> std::io::Result> { +pub fn spawn_attach_observer( + broker: Arc, +) -> std::io::Result> { std::thread::Builder::new() .name("attach-observer".to_string()) .spawn(move || run_observer(broker.stop_latch(), &|| broker.attachment_snapshot())) @@ -545,7 +547,12 @@ mod tests { #[test] fn an_unseen_link_owes_a_link_push_with_no_changed_node() { let seen = SeenAttach::new(); - let observed = vec![obs("ana", "sh-0", "t1", attach(Some("node-a"), &["node-b"]))]; + let observed = vec![obs( + "ana", + "sh-0", + "t1", + attach(Some("node-a"), &["node-b"]), + )]; let pushes = plan_attach_pushes(&seen, &observed); assert_eq!(pushes.len(), 1); assert_eq!(pushes[0].kind, PushKind::Link); @@ -579,7 +586,12 @@ mod tests { #[test] fn an_unchanged_link_and_attachment_owes_nothing() { let mut seen = SeenAttach::new(); - let observed = vec![obs("ana", "sh-0", "t1", attach(Some("node-a"), &["node-b"]))]; + let observed = vec![obs( + "ana", + "sh-0", + "t1", + attach(Some("node-a"), &["node-b"]), + )]; remember(&mut seen, &observed); assert!(plan_attach_pushes(&seen, &observed).is_empty()); } @@ -595,7 +607,12 @@ mod tests { ); let pushes = plan_attach_pushes( &seen, - &[obs("ana", "sh-0", "t1", attach(Some("node-a"), &["node-b"]))], + &[obs( + "ana", + "sh-0", + "t1", + attach(Some("node-a"), &["node-b"]), + )], ); assert_eq!(pushes.len(), 1); assert_eq!(pushes[0].kind, PushKind::State); @@ -691,7 +708,10 @@ mod tests { let mut live = HashMap::new(); live.insert("ana".to_string(), Attachment::default()); let t0 = 1_000_000u64; - assert!(plan_away(&mut mem, t0, &live).is_empty(), "the edge itself is not away"); + assert!( + plan_away(&mut mem, t0, &live).is_empty(), + "the edge itself is not away" + ); assert!( plan_away(&mut mem, t0 + AWAY_AFTER.as_millis() as u64 - 1, &live).is_empty(), "one millisecond short is still not away" diff --git a/crates/spt-daemon/src/autostart.rs b/crates/spt-daemon/src/autostart.rs index 0dbacf78..fd8c712c 100644 --- a/crates/spt-daemon/src/autostart.rs +++ b/crates/spt-daemon/src/autostart.rs @@ -79,7 +79,10 @@ fn emit_launched( } /// The replay loop over an explicit entry list — the seam the units drive. -fn replay_entries(broker_name: &str, entries: Vec) -> Vec { +fn replay_entries( + broker_name: &str, + entries: Vec, +) -> Vec { let mut outcomes = Vec::new(); if entries.is_empty() { return outcomes; @@ -118,7 +121,8 @@ fn replay_entries(broker_name: &str, entries: Vec`", - entry.id, entry.adapter + entry.id, + entry.adapter ); outcomes.push(ReplayOutcome::SkippedAdapter); continue; @@ -127,7 +131,8 @@ fn replay_entries(broker_name: &str, entries: Vec`", - entry.id, entry.adapter + entry.id, + entry.adapter ); outcomes.push(ReplayOutcome::SkippedAdapter); continue; @@ -157,13 +162,8 @@ fn replay_entries(broker_name: &str, entries: Vec String { let mut s = String::from("HEADSTART "); for i in 0..12 { - s.push_str(&format!("line-{i:02}-payload-body-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n")); + s.push_str(&format!( + "line-{i:02}-payload-body-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" + )); } s.push_str("TAILEND"); s diff --git a/crates/spt-daemon/src/brain.rs b/crates/spt-daemon/src/brain.rs index 4bf94112..b5dc012d 100644 --- a/crates/spt-daemon/src/brain.rs +++ b/crates/spt-daemon/src/brain.rs @@ -32,40 +32,41 @@ use interprocess::local_socket::prelude::*; use interprocess::local_socket::{SendHalf, Stream}; use crate::codec::{read_frame, write_frame}; -use crate::frame::{Envelope, Role}; use crate::effect::MintedOp; +use crate::frame::{Envelope, Role}; use crate::msg::{ - decode_bytes, encode_bytes, AdapterApplyReq, AppliedEvent, BrainRestarted, BrokerImageReply, - CoordinatorImageAnnounce, CoordinatorImageAnnounceReply, CoordinatorImageReply, StallEvictsReply, DisplacedEvent, - EndpointInjected, EndpointInputReq, ErrorEvent, ExitEvent, - InputReq, - KillReq, NetDialReq, NetDialed, NetPresenceEvent, NetPresenceSubscribeReq, NetSent, TeardownReq, KIND_TEARDOWN, - NetStatusReply, NetStreamData, NetStreamEof, NetStreamOpenReq, NetStreamOpened, NetStreamSendReq, - NetStreamSubscribeReq, NetStreamsReply, NetStreamOpenerReply, NetStreamOpenerReq, NetStreamRetireReq, NetStreamRetired, NetStreamUnsubscribeReq, NetStreamUnsubscribed, OutputEvent, MetMember, PairCodeSubmit, PairJoinReply, PairJoinReq, PairMeetReq, ResizeReq, - SessionsReply, SizeEvent, SpawnConflict, SpawnReq, Spawned, StreamLifetime, SubscribeOutcome, - SubscribeReq, SubscribedReply, ViewerEvictedEvent, - KIND_ADAPTER_APPLY, KIND_APPLIED, KIND_BRAIN_RESTART, KIND_BROKER_IMAGE, KIND_BROKER_IMAGE_REPLY, KIND_STALL_EVICTS, KIND_STALL_EVICTS_REPLY, KIND_VIEWER_EVICTED, - KIND_COORDINATOR_IMAGE, KIND_COORDINATOR_IMAGE_ANNOUNCE, KIND_COORDINATOR_IMAGE_ANNOUNCE_REPLY, KIND_COORDINATOR_IMAGE_REPLY, - KIND_BRAIN_RESTARTED, KIND_DISPLACED, KIND_ENDPOINT_INJECTED, KIND_ENDPOINT_INPUT, KIND_ERROR, KIND_EXIT, KIND_INPUT, KIND_KILL, KIND_NET_DIAL, - KIND_NET_DIALED, KIND_NET_DIAL_LOOPBACK, KIND_NET_DIAL_SUBMIT, KIND_NET_DIAL_SUBMITTED, - KIND_NET_PRESENCE_EVENT, KIND_NET_PRESENCE_SUBSCRIBE, - KIND_NET_SENT, - KIND_NET_STATUS, KIND_NET_STATUS_REPLY, KIND_NET_STREAMS, KIND_NET_STREAMS_REPLY, - KIND_NET_STREAM_DATA, KIND_NET_STREAM_EOF, KIND_NET_STREAM_OPEN, KIND_NET_STREAM_OPENED, - KIND_NET_STREAM_OPENER, KIND_NET_STREAM_OPENER_REPLY, KIND_NET_STREAM_RETIRE, KIND_NET_STREAM_RETIRED, - KIND_NET_STREAM_UNSUBSCRIBE, KIND_NET_STREAM_UNSUBSCRIBED, - KIND_MET_MEMBER, KIND_NET_STREAM_SEND, KIND_NET_STREAM_SUBSCRIBE, KIND_OUTPUT, KIND_PAIR_CODE_SUBMIT, KIND_PAIR_JOIN, KIND_PAIR_JOINED, KIND_PAIR_MEET, - KIND_RESIZE, KIND_SESSIONS, KIND_SESSIONS_REPLY, KIND_SIZE, KIND_SPAWN, KIND_SPAWNED, - KIND_SPAWN_CONFLICT, KIND_SPAWN_FRESH, - KIND_SUBSCRIBE, KIND_SUBSCRIBED, KIND_UNSUBSCRIBE, UnsubscribeReq, - BringUpReq, BroughtUpReply, KIND_BRING_UP, KIND_BROUGHT_UP, - SealCeremonyReq, SealCeremonyReply, KIND_SEAL_CEREMONY, KIND_SEAL_CEREMONY_REPLY, - SealEnrollReq, KIND_SEAL_ENROLL, - SealCeremonyOpenEvent, SealCeremonyCodeReq, SealCeremonyResultEvent, - KIND_SEAL_CEREMONY_OPEN, KIND_SEAL_CEREMONY_CODE, KIND_SEAL_CEREMONY_RESULT, + decode_bytes, encode_bytes, AdapterApplyReq, AppliedEvent, BrainRestarted, BringUpReq, + BrokerImageReply, BroughtUpReply, CoordinatorImageAnnounce, CoordinatorImageAnnounceReply, + CoordinatorImageReply, DisplacedEvent, EndpointInjected, EndpointInputReq, ErrorEvent, + ExitEvent, InputReq, KillReq, MetMember, NetDialReq, NetDialed, NetPresenceEvent, + NetPresenceSubscribeReq, NetSent, NetStatusReply, NetStreamData, NetStreamEof, + NetStreamOpenReq, NetStreamOpened, NetStreamOpenerReply, NetStreamOpenerReq, + NetStreamRetireReq, NetStreamRetired, NetStreamSendReq, NetStreamSubscribeReq, + NetStreamUnsubscribeReq, NetStreamUnsubscribed, NetStreamsReply, OutputEvent, PairCodeSubmit, + PairJoinReply, PairJoinReq, PairMeetReq, ResizeReq, SealCeremonyCodeReq, SealCeremonyOpenEvent, + SealCeremonyReply, SealCeremonyReq, SealCeremonyResultEvent, SealEnrollReq, SessionsReply, + SizeEvent, SpawnConflict, SpawnReq, Spawned, StallEvictsReply, StreamLifetime, + SubscribeOutcome, SubscribeReq, SubscribedReply, TeardownReq, UnsubscribeReq, + ViewerEvictedEvent, KIND_ADAPTER_APPLY, KIND_APPLIED, KIND_BRAIN_RESTART, KIND_BRAIN_RESTARTED, + KIND_BRING_UP, KIND_BROKER_IMAGE, KIND_BROKER_IMAGE_REPLY, KIND_BROUGHT_UP, + KIND_COORDINATOR_IMAGE, KIND_COORDINATOR_IMAGE_ANNOUNCE, KIND_COORDINATOR_IMAGE_ANNOUNCE_REPLY, + KIND_COORDINATOR_IMAGE_REPLY, KIND_DISPLACED, KIND_ENDPOINT_INJECTED, KIND_ENDPOINT_INPUT, + KIND_ERROR, KIND_EXIT, KIND_INPUT, KIND_KILL, KIND_MET_MEMBER, KIND_NET_DIAL, KIND_NET_DIALED, + KIND_NET_DIAL_LOOPBACK, KIND_NET_DIAL_SUBMIT, KIND_NET_DIAL_SUBMITTED, KIND_NET_PRESENCE_EVENT, + KIND_NET_PRESENCE_SUBSCRIBE, KIND_NET_SENT, KIND_NET_STATUS, KIND_NET_STATUS_REPLY, + KIND_NET_STREAMS, KIND_NET_STREAMS_REPLY, KIND_NET_STREAM_DATA, KIND_NET_STREAM_EOF, + KIND_NET_STREAM_OPEN, KIND_NET_STREAM_OPENED, KIND_NET_STREAM_OPENER, + KIND_NET_STREAM_OPENER_REPLY, KIND_NET_STREAM_RETIRE, KIND_NET_STREAM_RETIRED, + KIND_NET_STREAM_SEND, KIND_NET_STREAM_SUBSCRIBE, KIND_NET_STREAM_UNSUBSCRIBE, + KIND_NET_STREAM_UNSUBSCRIBED, KIND_OUTPUT, KIND_PAIR_CODE_SUBMIT, KIND_PAIR_JOIN, + KIND_PAIR_JOINED, KIND_PAIR_MEET, KIND_RESIZE, KIND_SEAL_CEREMONY, KIND_SEAL_CEREMONY_CODE, + KIND_SEAL_CEREMONY_OPEN, KIND_SEAL_CEREMONY_REPLY, KIND_SEAL_CEREMONY_RESULT, KIND_SEAL_ENROLL, + KIND_SESSIONS, KIND_SESSIONS_REPLY, KIND_SIZE, KIND_SPAWN, KIND_SPAWNED, KIND_SPAWN_CONFLICT, + KIND_SPAWN_FRESH, KIND_STALL_EVICTS, KIND_STALL_EVICTS_REPLY, KIND_SUBSCRIBE, KIND_SUBSCRIBED, + KIND_TEARDOWN, KIND_UNSUBSCRIBE, KIND_VIEWER_EVICTED, }; -use spt_net::net::attach::AttachIntent; use crate::transport::{send_hello, LocalSocketTransport}; +use spt_net::net::attach::AttachIntent; /// Wall-clock now in epoch milliseconds — the source for `gen_start` (matches /// the epoch-ms stamping used elsewhere in the tree; no date dependency). @@ -962,11 +963,7 @@ impl Brain { /// asynchronous — the exit waiter removes the row once the child is dead), /// which is also why the request is idempotent broker-side. // [impl->REQ-ENDPOINT-TEARDOWN-AUTHORITY] - pub fn teardown_session( - &mut self, - session_id: Option, - endpoint: &str, - ) -> io::Result<()> { + pub fn teardown_session(&mut self, session_id: Option, endpoint: &str) -> io::Result<()> { self.send( KIND_TEARDOWN, serde_json::to_value(TeardownReq { @@ -1472,7 +1469,15 @@ impl Brain { // [impl->REQ-VIEWER-SKIP-TO-LIVE-ON-EVICT] pub fn attach_skip_to_live(&mut self, session_id: u64, by: Option<&str>) -> io::Result<()> { self.session_id = Some(session_id); - self.subscribe_with(session_id, u64::MAX, AttachIntent::Viewer, 0, by.map(str::to_string), None, false)?; + self.subscribe_with( + session_id, + u64::MAX, + AttachIntent::Viewer, + 0, + by.map(str::to_string), + None, + false, + )?; self.session_cursors.insert(session_id, 0); self.next_seq = 0; Ok(()) @@ -1511,7 +1516,15 @@ impl Brain { ) -> io::Result<()> { self.session_id = Some(session_id); self.next_seq = from_seq; - self.subscribe_with(session_id, from_seq, AttachIntent::Viewer, 0, by.map(str::to_string), None, false)?; + self.subscribe_with( + session_id, + from_seq, + AttachIntent::Viewer, + 0, + by.map(str::to_string), + None, + false, + )?; self.session_cursors.insert(session_id, from_seq); Ok(()) } @@ -1582,7 +1595,15 @@ impl Brain { // to forbid. // [impl->REQ-BRAIN-RESUME-NO-CONTROL-STEAL] let intent = AttachIntent::Viewer; - self.subscribe_with(info.session_id, info.resume_seq, intent, 0, None, None, false)?; + self.subscribe_with( + info.session_id, + info.resume_seq, + intent, + 0, + None, + None, + false, + )?; resumed.push(info.session_id); } Ok(resumed) @@ -1637,7 +1658,6 @@ impl Brain { self.next_seq } - /// Query the broker-owned net endpoint's status (D4a): node id, dialable /// address, conn count — or `enabled: false` on a net-less broker. Reads /// until the reply (consuming interleaved events like [`Brain::spawn_session`]). @@ -2349,7 +2369,15 @@ impl Brain { /// as Viewer instead; Control is reserved for sessions the daemon brain drives. // [doc->REQ-BRAIN-RESUME-NO-CONTROL-STEAL] fn subscribe(&mut self, session_id: u64, from_seq: u64) -> io::Result<()> { - self.subscribe_with(session_id, from_seq, Self::SUBSCRIBE_INTENT, 0, None, None, false) + self.subscribe_with( + session_id, + from_seq, + Self::SUBSCRIBE_INTENT, + 0, + None, + None, + false, + ) } /// Release this connection's controller/viewer role on `session_id` @@ -2557,13 +2585,27 @@ mod tests { let now = Instant::now(); // Pump mode, 30s carrier: reply-read capped to the 10s budget. let d = peer_reply_deadline(Some(Duration::from_secs(30)), now).expect("pump = Some"); - assert_eq!(d, now + PEER_REPLY_READ_BUDGET, "capped at the 10s budget, not 30s"); - assert!(d < now + Duration::from_secs(30), "strictly before the carrier deadline"); + assert_eq!( + d, + now + PEER_REPLY_READ_BUDGET, + "capped at the 10s budget, not 30s" + ); + assert!( + d < now + Duration::from_secs(30), + "strictly before the carrier deadline" + ); // A carrier timeout SHORTER than the budget wins the min (never exceed it). let short = peer_reply_deadline(Some(Duration::from_secs(3)), now).unwrap(); - assert_eq!(short, now + Duration::from_secs(3), "min honors a shorter carrier bound"); + assert_eq!( + short, + now + Duration::from_secs(3), + "min honors a shorter carrier bound" + ); // Non-pump: unbounded. - assert!(peer_reply_deadline(None, now).is_none(), "non-pump stays unbounded"); + assert!( + peer_reply_deadline(None, now).is_none(), + "non-pump stays unbounded" + ); } // [unit->REQ-PUMP-DIAL-FASTFAIL] the reclassification: a connect-then-silent @@ -2573,7 +2615,11 @@ mod tests { #[test] fn reclassify_peer_reply_maps_timeout_off_poison() { let t = reclassify_peer_reply_err(io::Error::new(io::ErrorKind::TimedOut, "silent peer")); - assert_ne!(t.kind(), io::ErrorKind::TimedOut, "no longer the poison kind"); + assert_ne!( + t.kind(), + io::ErrorKind::TimedOut, + "no longer the poison kind" + ); assert_eq!(t.kind(), io::ErrorKind::Other); let passthrough = reclassify_peer_reply_err(io::Error::new(io::ErrorKind::BrokenPipe, "carrier gone")); @@ -2678,7 +2724,9 @@ mod tests { // A FORWARD JUMP (seq 5, want 1) is a hard `output gap` error on the legacy // path — a cold brain treats a skipped seq as a lost chunk, never silently. stub.feed.send(output_envelope(sid, 5, b"jumped")).unwrap(); - let err = brain.read_event().expect_err("a cold brain rejects a forward gap"); + let err = brain + .read_event() + .expect_err("a cold brain rejects a forward gap"); assert_eq!(err.kind(), io::ErrorKind::InvalidData); assert!( err.to_string().contains("output gap"), @@ -2724,7 +2772,10 @@ mod tests { stub.feed .send(output_envelope(sid, seq, format!("c{seq}").as_bytes())) .unwrap(); - match brain.read_event().expect("contiguous controller frame accepted") { + match brain + .read_event() + .expect("contiguous controller frame accepted") + { BrokerEvent::Output { seq: got, .. } => assert_eq!(got, seq), other => panic!("expected Output({seq}), got {other:?}"), } @@ -2759,13 +2810,22 @@ mod tests { // ring replays 3,4,5 from the floor; the strict cursor (re-seeded to 3 by // attach_as) ACCEPTS each contiguously — exactly-once re-fetch, no re-gap. brain - .attach_as(sid, brain.controller_resume_floor(), AttachIntent::Control, 0, Some("node-A")) + .attach_as( + sid, + brain.controller_resume_floor(), + AttachIntent::Control, + 0, + Some("node-A"), + ) .expect("controller resume from floor"); for seq in 3u64..=5 { stub.feed .send(output_envelope(sid, seq, format!("r{seq}").as_bytes())) .unwrap(); - match brain.read_event().expect("ring-replayed floor frame accepted") { + match brain + .read_event() + .expect("ring-replayed floor frame accepted") + { BrokerEvent::Output { seq: got, .. } => assert_eq!(got, seq), other => panic!("expected re-fetched Output({seq}), got {other:?}"), } @@ -2783,7 +2843,13 @@ mod tests { // UNCHANGED across two consecutive resumes — and returns // `ControllerIrrecoverablyBehind { floor }` rather than looping forever. brain - .attach_as(sid, brain.controller_resume_floor(), AttachIntent::Control, 0, Some("node-A")) + .attach_as( + sid, + brain.controller_resume_floor(), + AttachIntent::Control, + 0, + Some("node-A"), + ) .expect("controller second resume"); stub.feed.send(output_envelope(sid, 9, b"rolled")).unwrap(); let err = brain @@ -2842,7 +2908,10 @@ mod tests { stub.feed .send(sync_output_envelope(sid, 6, b"\x1b[?1049l-sync")) .unwrap(); - match brain.read_event().expect("flagged forward jump accepted (legacy path)") { + match brain + .read_event() + .expect("flagged forward jump accepted (legacy path)") + { BrokerEvent::Output { seq, bytes, .. } => { assert_eq!(seq, 6, "the sync frame itself is delivered"); assert_eq!(bytes, b"\x1b[?1049l-sync"); @@ -2863,9 +2932,14 @@ mod tests { // Flagged BACKWARD (a replayed boundary re-send of an old sync frame): // dedup-dropped, cursor untouched — feed a contiguous probe behind it to // prove the backward frame produced NO event and NO rewind. - stub.feed.send(sync_output_envelope(sid, 3, b"stale-sync")).unwrap(); + stub.feed + .send(sync_output_envelope(sid, 3, b"stale-sync")) + .unwrap(); stub.feed.send(output_envelope(sid, 8, b"probe")).unwrap(); - match brain.read_event().expect("the backward flagged frame is silently deduped") { + match brain + .read_event() + .expect("the backward flagged frame is silently deduped") + { BrokerEvent::Output { seq, bytes, .. } => { assert_eq!(seq, 8, "the NEXT event is the probe — never the stale sync"); assert_eq!(bytes, b"probe"); @@ -2876,20 +2950,34 @@ mod tests { // ── RESUME-MODE map path ──────────────────────────────────────────── let (mut brain, stub) = brain_with_stub(); - brain.attach_as_viewer_snap(sid, 0, Some("node-A")).expect("snap viewer"); + brain + .attach_as_viewer_snap(sid, 0, Some("node-A")) + .expect("snap viewer"); stub.feed.send(output_envelope(sid, 0, b"v0")).unwrap(); brain.read_event().expect("seq 0 accepted"); stub.feed .send(sync_output_envelope(sid, 6, b"sync-frame")) .unwrap(); - match brain.read_event().expect("flagged forward jump accepted (map path)") { + match brain + .read_event() + .expect("flagged forward jump accepted (map path)") + { BrokerEvent::Output { seq, .. } => assert_eq!(seq, 6), other => panic!("expected Output(6), got {other:?}"), } - assert_eq!(brain.session_cursor(sid), Some(7), "map cursor snapped to 7"); - stub.feed.send(sync_output_envelope(sid, 2, b"stale")).unwrap(); + assert_eq!( + brain.session_cursor(sid), + Some(7), + "map cursor snapped to 7" + ); + stub.feed + .send(sync_output_envelope(sid, 2, b"stale")) + .unwrap(); stub.feed.send(output_envelope(sid, 7, b"probe")).unwrap(); - match brain.read_event().expect("backward flagged frame deduped on the map path") { + match brain + .read_event() + .expect("backward flagged frame deduped on the map path") + { BrokerEvent::Output { seq, .. } => assert_eq!(seq, 7, "probe, not the stale sync"), other => panic!("expected Output(7), got {other:?}"), } @@ -2904,9 +2992,10 @@ mod tests { fn an_old_broker_wire_without_the_sync_key_keeps_every_legacy_path() { let sid = 1u64; // The absent key deserializes to false (the resume_seq additive shape). - let old: OutputEvent = serde_json::from_str( - &format!(r#"{{"session_id":{sid},"seq":9,"data_b64":"{}"}}"#, encode_bytes(b"x")), - ) + let old: OutputEvent = serde_json::from_str(&format!( + r#"{{"session_id":{sid},"seq":9,"data_b64":"{}"}}"#, + encode_bytes(b"x") + )) .expect("old-broker OutputEvent parses"); assert!(!old.sync, "absent sync key -> false"); @@ -2923,13 +3012,18 @@ mod tests { .unwrap(), ); stub.feed.send(repaint).unwrap(); - match brain.read_event().expect("cold baseline accepts the unflagged pseudo-seq") { + match brain + .read_event() + .expect("cold baseline accepts the unflagged pseudo-seq") + { BrokerEvent::Output { seq, .. } => assert_eq!(seq, 4), other => panic!("expected Output(4), got {other:?}"), } // Strict afterwards: an unflagged forward jump is still a hard gap. stub.feed.send(output_envelope(sid, 9, b"jump")).unwrap(); - let err = brain.read_event().expect_err("unflagged jump stays reject-gap"); + let err = brain + .read_event() + .expect_err("unflagged jump stays reject-gap"); assert!(err.to_string().contains("output gap")); } @@ -2972,9 +3066,15 @@ mod tests { // ACCEPT it (the broker's Mutex-held replay cannot reorder, so a forward // jump is only ever a legitimate post-eviction ring-floor clamp). stub.feed.send(output_envelope(sid, 12, b"LIVE-A")).unwrap(); - match brain.read_event().expect("post-eviction forward jump accepted") { + match brain + .read_event() + .expect("post-eviction forward jump accepted") + { BrokerEvent::Output { seq, bytes, .. } => { - assert_eq!(seq, 12, "the forward-jumped live seq is accepted, not rejected"); + assert_eq!( + seq, 12, + "the forward-jumped live seq is accepted, not rejected" + ); assert_eq!(bytes, b"LIVE-A"); } other => panic!("expected Output(12) via snap-above, got {other:?}"), @@ -3048,10 +3148,18 @@ mod tests { // The ring rolled between reads: the next Output frame carries a seq far // ABOVE the cursor (4504 while cursor is 100 — the legacy path would fatal // `output gap: got 4504 want 100`). Snap-above must ACCEPT it. - stub.feed.send(output_envelope(sid, 4504, b"ROLLED")).unwrap(); - match brain.read_event().expect("pre-eviction forward ring-roll gap accepted") { + stub.feed + .send(output_envelope(sid, 4504, b"ROLLED")) + .unwrap(); + match brain + .read_event() + .expect("pre-eviction forward ring-roll gap accepted") + { BrokerEvent::Output { seq, bytes, .. } => { - assert_eq!(seq, 4504, "the forward-jumped live seq is accepted, not rejected"); + assert_eq!( + seq, 4504, + "the forward-jumped live seq is accepted, not rejected" + ); assert_eq!(bytes, b"ROLLED"); } other => panic!("expected Output(4504) via snap-above, got {other:?}"), @@ -3065,9 +3173,13 @@ mod tests { // From there it tracks contiguously and DEDUPS below the cursor: seq 4505 // accepted, the stale re-send (seq 4504, already delivered) is DEDUPED (not a // gap, not re-emitted), seq 4506 accepted. - stub.feed.send(output_envelope(sid, 4505, b"LIVE-B")).unwrap(); + stub.feed + .send(output_envelope(sid, 4505, b"LIVE-B")) + .unwrap(); stub.feed.send(output_envelope(sid, 4504, b"DUP")).unwrap(); // dedup below cursor - stub.feed.send(output_envelope(sid, 4506, b"LIVE-C")).unwrap(); + stub.feed + .send(output_envelope(sid, 4506, b"LIVE-C")) + .unwrap(); let mut accepted = Vec::new(); for _ in 0..2 { match brain.read_event().expect("subsequent live frames") { diff --git a/crates/spt-daemon/src/brainproc.rs b/crates/spt-daemon/src/brainproc.rs index a327d0f4..f59f1bef 100644 --- a/crates/spt-daemon/src/brainproc.rs +++ b/crates/spt-daemon/src/brainproc.rs @@ -283,7 +283,9 @@ pub fn run_brain(generation: u64, reason: StartReason) -> io::Result<()> { ) } Ok(_) => {} - Err(e) => spt_proto::emit_line_err!("BRAIN_RESUME_NONFATAL: {e} — no sessions resumed, continuing"), + Err(e) => spt_proto::emit_line_err!( + "BRAIN_RESUME_NONFATAL: {e} — no sessions resumed, continuing" + ), } // [impl->REQ-BRAIN-READY-WINDOW-OBSERVABLE] stretch 2 of 3, and the one most // likely to be the stall: the ALWAYS-TAKEN arm today is `Ok(_) => {}` (the @@ -376,7 +378,9 @@ pub fn run_brain(generation: u64, reason: StartReason) -> io::Result<()> { let status = match brain.net_status() { Ok(s) => s, Err(e) => { - spt_proto::emit_line_err!("BRAIN_BROKER_LOST: {e} — exiting for supervised respawn"); + spt_proto::emit_line_err!( + "BRAIN_BROKER_LOST: {e} — exiting for supervised respawn" + ); return Err(e); } }; @@ -617,7 +621,12 @@ pub trait TrialEnv { fn record_promoted(&self, version: u64); /// Correct the record: the candidate failed readiness. Persist /// `RolledBack{…}` and fire the loud, resurfacing rollback notif. - fn record_rolled_back(&self, quarantine_version: u64, running_version: u64, rollback_binary: &str); + fn record_rolled_back( + &self, + quarantine_version: u64, + running_version: u64, + rollback_binary: &str, + ); /// The `exe_hash` the candidate stamped in `brain.ready` (the bytes it is /// actually running), or `None` if absent/garbled — degrades the promotion /// bytes-gate to readiness-only (KH 6.11, N-1-safe). @@ -711,7 +720,12 @@ impl TrialEnv for ProductionTrialEnv { // produce — see `fire_rollback_notif`). dismiss_update_notifs_on_apply(); } - fn record_rolled_back(&self, quarantine_version: u64, running_version: u64, rollback_binary: &str) { + fn record_rolled_back( + &self, + quarantine_version: u64, + running_version: u64, + rollback_binary: &str, + ) { let cache = self.cache(); let _ = cache.record_applied_state(&AppliedRecord::RolledBack { quarantine_version, @@ -767,7 +781,9 @@ impl TrialEnv for ProductionTrialEnv { // [impl->REQ-NOTIF-SEAM-DISMISS] fn dismiss_update_notifs_on_apply() { let Ok(store) = spt_store::notif::NotifStore::open() else { - spt_proto::emit_line_err!("UPDATE_DISMISS_DROP: notif store unavailable [REQ-NOTIF-SEAM-DISMISS]"); + spt_proto::emit_line_err!( + "UPDATE_DISMISS_DROP: notif store unavailable [REQ-NOTIF-SEAM-DISMISS]" + ); return; }; for (subnet, _) in &crate::notif::NotifSurfacePolicy::load().subnets { @@ -776,7 +792,9 @@ fn dismiss_update_notifs_on_apply() { crate::notif::NOTIF_KEY_ROLLBACK, ] { if let Err(e) = store.dismiss_by_coalesce_key(subnet, key) { - spt_proto::emit_line_err!("UPDATE_DISMISS_FAIL:{subnet}:{key}:{e} [REQ-NOTIF-SEAM-DISMISS]"); + spt_proto::emit_line_err!( + "UPDATE_DISMISS_FAIL:{subnet}:{key}:{e} [REQ-NOTIF-SEAM-DISMISS]" + ); } } } @@ -962,9 +980,9 @@ pub fn supervise_brain( // trial, default binary" — the supervisor never panics on the record. let record = env.applied_state(); let binary: Option = match &record { - Some(AppliedRecord::RolledBack { rollback_binary, .. }) => { - Some(PathBuf::from(rollback_binary)) - } + Some(AppliedRecord::RolledBack { + rollback_binary, .. + }) => Some(PathBuf::from(rollback_binary)), _ => None, }; let is_trial = matches!(record, Some(AppliedRecord::AppliedPending { .. })); @@ -1006,7 +1024,9 @@ pub fn supervise_brain( // onto the renamed old binary) fails the trial → kill + // rollback, never a falsely-`applied` record. let version = match &record { - Some(AppliedRecord::AppliedPending { version, .. }) => Some(*version), + Some(AppliedRecord::AppliedPending { version, .. }) => { + Some(*version) + } _ => None, }; if let Some(version) = version { @@ -1085,7 +1105,9 @@ pub fn supervise_brain( } match child.try_wait() { Ok(Some(status)) => { - spt_proto::emit_line_err!("BRAIN_EXIT: brain child exited ({status}) — respawning"); + spt_proto::emit_line_err!( + "BRAIN_EXIT: brain child exited ({status}) — respawning" + ); break; } Ok(None) => thread::sleep(TICK), @@ -1110,12 +1132,17 @@ pub fn supervise_brain( if planned { reason = StartReason::Update; backoff = base; - spt_proto::emit_line_err!("BRAIN_RESTART: planned update respawn (generation {generation})"); + spt_proto::emit_line_err!( + "BRAIN_RESTART: planned update respawn (generation {generation})" + ); continue; } reason = StartReason::Crash; backoff = next_backoff(backoff, started.elapsed(), base); - spt_proto::emit_line_err!("BRAIN_RESTART: supervised respawn in {}s", backoff.as_secs()); + spt_proto::emit_line_err!( + "BRAIN_RESTART: supervised respawn in {}s", + backoff.as_secs() + ); sleep_backoff(backoff, stop); } } @@ -1494,11 +1521,25 @@ mod tests { fn brain_child_args_carry_generation_and_reason() { assert_eq!( brain_child_args(7, StartReason::Update), - vec!["daemon", "brain", "--generation", "7", "--start-reason", "update"] + vec![ + "daemon", + "brain", + "--generation", + "7", + "--start-reason", + "update" + ] ); assert_eq!( brain_child_args(0, StartReason::Cold), - vec!["daemon", "brain", "--generation", "0", "--start-reason", "cold"] + vec![ + "daemon", + "brain", + "--generation", + "0", + "--start-reason", + "cold" + ] ); } @@ -1568,11 +1609,14 @@ mod tests { Some(7) ); // Staleness is visible at the primitive: gen N−1 ≠ the gen-N a gate seeks. - let stale = parse_ready_generation( - &serde_json::json!({"pid": 4321, "generation": 6}).to_string(), - ); + let stale = + parse_ready_generation(&serde_json::json!({"pid": 4321, "generation": 6}).to_string()); assert_eq!(stale, Some(6)); - assert_ne!(stale, Some(7), "a gen-6 stamp must not satisfy a gen-7 gate"); + assert_ne!( + stale, + Some(7), + "a gen-6 stamp must not satisfy a gen-7 gate" + ); // Fail-safe: legacy bare-pid text, garbage, and a stampless body → None. assert_eq!(parse_ready_generation("4321"), None, "legacy bare pid"); assert_eq!(parse_ready_generation("{ not json"), None, "garbage"); @@ -1591,8 +1635,11 @@ mod tests { let dir = tempfile::tempdir().unwrap(); let path = dir.path().join("brain.ready"); assert_eq!(ready_generation_at(&path), None, "absent file → not-ready"); - std::fs::write(&path, serde_json::json!({"pid": 1, "generation": 42}).to_string()) - .unwrap(); + std::fs::write( + &path, + serde_json::json!({"pid": 1, "generation": 42}).to_string(), + ) + .unwrap(); assert_eq!(ready_generation_at(&path), Some(42)); } @@ -1605,8 +1652,7 @@ mod tests { // Present → Some(hash). assert_eq!( parse_ready_exe_hash( - &serde_json::json!({"pid": 1, "generation": 3, "exe_hash": "deadbeef"}) - .to_string() + &serde_json::json!({"pid": 1, "generation": 3, "exe_hash": "deadbeef"}).to_string() ), Some("deadbeef".to_string()) ); @@ -1813,14 +1859,28 @@ mod tests { fast_child() }, ); - assert_eq!(env.promotions.lock().unwrap().as_slice(), &[7], "promoted once"); + assert_eq!( + env.promotions.lock().unwrap().as_slice(), + &[7], + "promoted once" + ); assert!(env.rollbacks.lock().unwrap().is_empty(), "no rollback"); assert_eq!(env.notifs.load(Ordering::Relaxed), 0, "no rollback notif"); - assert!(env.clears.load(Ordering::Relaxed) >= 1, "ready cleared before the trial spawn"); + assert!( + env.clears.load(Ordering::Relaxed) >= 1, + "ready cleared before the trial spawn" + ); let s = spawns.lock().unwrap(); - assert_eq!(s[0].1, StartReason::Cold, "first spawn is the cold trial candidate"); + assert_eq!( + s[0].1, + StartReason::Cold, + "first spawn is the cold trial candidate" + ); assert_eq!(s[0].2, None, "candidate spawns the default current_exe"); - assert_eq!(s[1].2, None, "a later crash respawns the SAME accepted binary, not a rollback"); + assert_eq!( + s[1].2, None, + "a later crash respawns the SAME accepted binary, not a rollback" + ); } /// (DRAINED gate — RED-first) A candidate that signals ready but whose OLD @@ -1869,7 +1929,11 @@ mod tests { &[(6, 5, "/good/spt.old-6".to_string())], "the never-drained candidate is killed + rolled back (conservative, never a false-promote)" ); - assert_eq!(env.notifs.load(Ordering::Relaxed), 1, "one loud rollback notif"); + assert_eq!( + env.notifs.load(Ordering::Relaxed), + 1, + "one loud rollback notif" + ); } /// (DRAINED gate — latch releases) A ready candidate whose old generation drains @@ -1952,9 +2016,15 @@ mod tests { let x = TestTrialEnv::pending(8, "/g/spt.old-8").with_hashes(Some("abc"), Some("xyz")); assert!(matches!(bytes_gate(&x, 8), BytesGate::Mismatch)); let ready_absent = TestTrialEnv::pending(8, "/g/spt.old-8").with_hashes(None, Some("abc")); - assert!(matches!(bytes_gate(&ready_absent, 8), BytesGate::Unverified)); + assert!(matches!( + bytes_gate(&ready_absent, 8), + BytesGate::Unverified + )); let staged_absent = TestTrialEnv::pending(8, "/g/spt.old-8").with_hashes(Some("abc"), None); - assert!(matches!(bytes_gate(&staged_absent, 8), BytesGate::Unverified)); + assert!(matches!( + bytes_gate(&staged_absent, 8), + BytesGate::Unverified + )); } /// (KH 6.11 — Half 2 integration) A candidate that signals ready but is @@ -1999,7 +2069,11 @@ mod tests { 1, "rolled back once on the bytes mismatch" ); - assert_eq!(env.notifs.load(Ordering::Relaxed), 1, "loud rollback notif fired"); + assert_eq!( + env.notifs.load(Ordering::Relaxed), + 1, + "loud rollback notif fired" + ); } /// (KH 6.11 — Half 2 integration) A candidate ready AND running the staged @@ -2065,10 +2139,11 @@ mod tests { env.as_ref(), Duration::from_secs(5), move |gen, reason, binary| { - spawns_c - .lock() - .unwrap() - .push((gen, reason, binary.map(|p| p.display().to_string()))); + spawns_c.lock().unwrap().push(( + gen, + reason, + binary.map(|p| p.display().to_string()), + )); // The candidate never signals ready and exits at once (fast_child); // once selection switches to the rollback binary, stop. if binary.is_some() { @@ -2082,13 +2157,22 @@ mod tests { &[(9, 8, "/good/spt.old-9".to_string())], "rolled back exactly once, quarantine=N running=N-1" ); - assert_eq!(env.notifs.load(Ordering::Relaxed), 1, "one loud rollback notif"); + assert_eq!( + env.notifs.load(Ordering::Relaxed), + 1, + "one loud rollback notif" + ); assert!(env.promotions.lock().unwrap().is_empty(), "never promoted"); let s = spawns.lock().unwrap(); let reasons: Vec = s.iter().map(|(_, r, _)| *r).collect(); assert_eq!( reasons, - vec![StartReason::Cold, StartReason::Crash, StartReason::Crash, StartReason::Crash], + vec![ + StartReason::Cold, + StartReason::Crash, + StartReason::Crash, + StartReason::Crash + ], "K=3 trial spawns (Cold then Crash×2) all gated, then the rollback respawn" ); assert_eq!(s[0].2, None, "trial candidate = current_exe"); @@ -2097,7 +2181,11 @@ mod tests { Some("/good/spt.old-9"), "after rollback, selection switches to the rollback binary" ); - assert_eq!(env.clears.load(Ordering::Relaxed), 3, "ready cleared before each of the 3 trial spawns"); + assert_eq!( + env.clears.load(Ordering::Relaxed), + 3, + "ready cleared before each of the 3 trial spawns" + ); } /// (3/A11) Alive-but-never-ready: the window elapses with the candidate alive @@ -2142,7 +2230,11 @@ mod tests { &[(5, 4, "/good/spt.old-5".to_string())], "alive-never-ready rolls back" ); - assert_eq!(env.notifs.load(Ordering::Relaxed), 1, "one loud rollback notif"); + assert_eq!( + env.notifs.load(Ordering::Relaxed), + 1, + "one loud rollback notif" + ); assert!(env.promotions.lock().unwrap().is_empty(), "never promoted"); } @@ -2312,7 +2404,10 @@ mod tests { "a fresh broker reading a RolledBack record spawns the good binary, not current_exe" ); assert!(env.promotions.lock().unwrap().is_empty()); - assert!(env.rollbacks.lock().unwrap().is_empty(), "no NEW rollback — it is the recovery steady state"); + assert!( + env.rollbacks.lock().unwrap().is_empty(), + "no NEW rollback — it is the recovery steady state" + ); } /// REGISTRY-LIFECYCLE R1: the executable digest is COMPUTED exactly once diff --git a/crates/spt-daemon/src/broker.rs b/crates/spt-daemon/src/broker.rs index 3d607c0d..2979c6e2 100644 --- a/crates/spt-daemon/src/broker.rs +++ b/crates/spt-daemon/src/broker.rs @@ -34,7 +34,9 @@ use std::collections::{HashMap, HashSet, VecDeque}; use std::io; use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, AtomicUsize, Ordering}; -use std::sync::mpsc::{channel, sync_channel, Receiver, RecvTimeoutError, Sender, SyncSender, TrySendError}; +use std::sync::mpsc::{ + channel, sync_channel, Receiver, RecvTimeoutError, Sender, SyncSender, TrySendError, +}; use std::sync::{Arc, Mutex, OnceLock}; use std::thread::{self, JoinHandle}; use std::time::{Duration, Instant}; @@ -51,33 +53,38 @@ use crate::conn::{BrokerConn, ConnWrite}; use crate::effect::{EffectJournal, EffectKey, EffectKind, Minter, Outcome}; use crate::frame::{Envelope, Role}; use crate::msg::{ - applied_envelope, decode_bytes, displaced_envelope, endpoint_injected_envelope, - evicted_envelope, net_dialed_envelope, output_envelope, - size_envelope, subscribed_envelope, sync_output_envelope, AdapterApplyReq, BrainRestarted, EndpointInputReq, - ErrorEvent, ExitEvent, InputReq, KillReq, NetDialReq, NetPresenceSubscribeReq, NetSent, TeardownReq, KIND_TEARDOWN, - BrokerImageReply, CoordinatorImageAnnounce, CoordinatorImageAnnounceReply, CoordinatorImageReply, - StallEvictsReply, NetStatusReply, NetStreamOpenReq, NetStreamOpened, NetStreamSendReq, NetStreamSubscribeReq, - NetStreamsReply, NetStreamOpenerReply, NetStreamOpenerReq, NetStreamRetireReq, NetStreamRetired, NetStreamUnsubscribeReq, NetStreamUnsubscribed, MetMember, PairCodeSubmit, PairJoinReply, PairJoinReq, PairMeetReq, ResizeReq, SessionInfo, SessionsReply, SpawnReq, - SpawnConflict, Spawned, SubscribeOutcome, SubscribeReq, UnsubscribeReq, KIND_BRAIN_RESTART, KIND_BRAIN_RESTARTED, KIND_ENDPOINT_INPUT, KIND_ERROR, KIND_EXIT, - KIND_INPUT, KIND_KILL, KIND_NET_DIAL, KIND_NET_DIAL_LOOPBACK, KIND_NET_DIAL_SUBMIT, - KIND_NET_DIAL_SUBMITTED, KIND_NET_PRESENCE_SUBSCRIBE, - KIND_NET_SENT, - KIND_ADAPTER_APPLY, KIND_APPLIED, - KIND_BROKER_IMAGE, KIND_BROKER_IMAGE_REPLY, KIND_STALL_EVICTS, KIND_STALL_EVICTS_REPLY, - KIND_COORDINATOR_IMAGE, KIND_COORDINATOR_IMAGE_ANNOUNCE, KIND_COORDINATOR_IMAGE_ANNOUNCE_REPLY, - KIND_COORDINATOR_IMAGE_REPLY, - KIND_NET_STATUS, KIND_NET_STATUS_REPLY, KIND_NET_STREAMS, KIND_NET_STREAMS_REPLY, - KIND_NET_STREAM_OPEN, KIND_NET_STREAM_OPENED, KIND_NET_STREAM_OPENER, KIND_NET_STREAM_OPENER_REPLY, KIND_NET_STREAM_RETIRE, KIND_NET_STREAM_RETIRED, KIND_NET_STREAM_SEND, KIND_NET_STREAM_SUBSCRIBE, - KIND_NET_STREAM_UNSUBSCRIBE, KIND_NET_STREAM_UNSUBSCRIBED, - KIND_MET_MEMBER, KIND_PAIR_CODE_SUBMIT, KIND_PAIR_JOIN, KIND_PAIR_JOINED, KIND_PAIR_MEET, KIND_RESIZE, KIND_SESSIONS, KIND_SESSIONS_REPLY, KIND_SPAWN, - BringUpReq, BroughtUpReply, BRING_UP_ADMITTED, BRING_UP_ADMIT_PREFIX, BRING_UP_ALREADY_LIVE, BRING_UP_REFUSED, KIND_BRING_UP, KIND_BROUGHT_UP, - SealCeremonyReq, SealCeremonyReply, SealCeremonyOpenEvent, SealCeremonyCodeReq, SealCeremonyResultEvent, - KIND_SEAL_CEREMONY, KIND_SEAL_CEREMONY_REPLY, KIND_SEAL_CEREMONY_OPEN, KIND_SEAL_CEREMONY_CODE, KIND_SEAL_CEREMONY_RESULT, - SEAL_CEREMONY_ADMITTED, SEAL_CEREMONY_REFUSED, SEAL_CEREMONY_THROTTLED, SEAL_CEREMONY_CANCELLED, SEAL_NO_CEREMONY_SURFACE, - SEAL_CEREMONY_CONTENT_MAX_CHARS, SEAL_CEREMONY_CONTENT_TOO_LONG, SEAL_CEREMONY_CONTENT_NOT_UTF8, - SealEnrollReq, KIND_SEAL_ENROLL, SEAL_ENROLL_ALREADY_ENROLLED, SEAL_ENROLLED, - SEAL_FIDO2_PROOF_REFUSED, encode_bytes, - KIND_SPAWNED, KIND_SPAWN_CONFLICT, KIND_SPAWN_FRESH, KIND_SUBSCRIBE, KIND_UNSUBSCRIBE, + applied_envelope, decode_bytes, displaced_envelope, encode_bytes, endpoint_injected_envelope, + evicted_envelope, net_dialed_envelope, output_envelope, size_envelope, subscribed_envelope, + sync_output_envelope, AdapterApplyReq, BrainRestarted, BringUpReq, BrokerImageReply, + BroughtUpReply, CoordinatorImageAnnounce, CoordinatorImageAnnounceReply, CoordinatorImageReply, + EndpointInputReq, ErrorEvent, ExitEvent, InputReq, KillReq, MetMember, NetDialReq, + NetPresenceSubscribeReq, NetSent, NetStatusReply, NetStreamOpenReq, NetStreamOpened, + NetStreamOpenerReply, NetStreamOpenerReq, NetStreamRetireReq, NetStreamRetired, + NetStreamSendReq, NetStreamSubscribeReq, NetStreamUnsubscribeReq, NetStreamUnsubscribed, + NetStreamsReply, PairCodeSubmit, PairJoinReply, PairJoinReq, PairMeetReq, ResizeReq, + SealCeremonyCodeReq, SealCeremonyOpenEvent, SealCeremonyReply, SealCeremonyReq, + SealCeremonyResultEvent, SealEnrollReq, SessionInfo, SessionsReply, SpawnConflict, SpawnReq, + Spawned, StallEvictsReply, SubscribeOutcome, SubscribeReq, TeardownReq, UnsubscribeReq, + BRING_UP_ADMITTED, BRING_UP_ADMIT_PREFIX, BRING_UP_ALREADY_LIVE, BRING_UP_REFUSED, + KIND_ADAPTER_APPLY, KIND_APPLIED, KIND_BRAIN_RESTART, KIND_BRAIN_RESTARTED, KIND_BRING_UP, + KIND_BROKER_IMAGE, KIND_BROKER_IMAGE_REPLY, KIND_BROUGHT_UP, KIND_COORDINATOR_IMAGE, + KIND_COORDINATOR_IMAGE_ANNOUNCE, KIND_COORDINATOR_IMAGE_ANNOUNCE_REPLY, + KIND_COORDINATOR_IMAGE_REPLY, KIND_ENDPOINT_INPUT, KIND_ERROR, KIND_EXIT, KIND_INPUT, + KIND_KILL, KIND_MET_MEMBER, KIND_NET_DIAL, KIND_NET_DIAL_LOOPBACK, KIND_NET_DIAL_SUBMIT, + KIND_NET_DIAL_SUBMITTED, KIND_NET_PRESENCE_SUBSCRIBE, KIND_NET_SENT, KIND_NET_STATUS, + KIND_NET_STATUS_REPLY, KIND_NET_STREAMS, KIND_NET_STREAMS_REPLY, KIND_NET_STREAM_OPEN, + KIND_NET_STREAM_OPENED, KIND_NET_STREAM_OPENER, KIND_NET_STREAM_OPENER_REPLY, + KIND_NET_STREAM_RETIRE, KIND_NET_STREAM_RETIRED, KIND_NET_STREAM_SEND, + KIND_NET_STREAM_SUBSCRIBE, KIND_NET_STREAM_UNSUBSCRIBE, KIND_NET_STREAM_UNSUBSCRIBED, + KIND_PAIR_CODE_SUBMIT, KIND_PAIR_JOIN, KIND_PAIR_JOINED, KIND_PAIR_MEET, KIND_RESIZE, + KIND_SEAL_CEREMONY, KIND_SEAL_CEREMONY_CODE, KIND_SEAL_CEREMONY_OPEN, KIND_SEAL_CEREMONY_REPLY, + KIND_SEAL_CEREMONY_RESULT, KIND_SEAL_ENROLL, KIND_SESSIONS, KIND_SESSIONS_REPLY, KIND_SPAWN, + KIND_SPAWNED, KIND_SPAWN_CONFLICT, KIND_SPAWN_FRESH, KIND_STALL_EVICTS, + KIND_STALL_EVICTS_REPLY, KIND_SUBSCRIBE, KIND_TEARDOWN, KIND_UNSUBSCRIBE, + SEAL_CEREMONY_ADMITTED, SEAL_CEREMONY_CANCELLED, SEAL_CEREMONY_CONTENT_MAX_CHARS, + SEAL_CEREMONY_CONTENT_NOT_UTF8, SEAL_CEREMONY_CONTENT_TOO_LONG, SEAL_CEREMONY_REFUSED, + SEAL_CEREMONY_THROTTLED, SEAL_ENROLLED, SEAL_ENROLL_ALREADY_ENROLLED, SEAL_FIDO2_PROOF_REFUSED, + SEAL_NO_CEREMONY_SURFACE, }; use crate::nethost::{NetHost, NET_EFFECT_SESSION}; use crate::translation::{key_to_bytes, InjectFloor, KeyCmd, ToBinary, TranslationChild}; @@ -299,7 +306,10 @@ impl Drop for WakeClaimGuard<'_> { /// re-opening, one wake later, exactly the double-create this guard exists to /// close. Pure over the map so the no-op is a unit. fn release_claim(map: &mut HashMap, endpoint: &str, generation: u64) { - if map.get(endpoint).is_some_and(|c| c.generation == generation) { + if map + .get(endpoint) + .is_some_and(|c| c.generation == generation) + { map.remove(endpoint); } } @@ -418,8 +428,8 @@ fn zombie_verdict( past_grace: bool, ) -> bool { match wrapper_alive { - None => false, // no probeable pid — never guess - Some(false) => true, // dead root, surviving record — always a zombie + None => false, // no probeable pid — never guess + Some(false) => true, // dead root, surviving record — always a zombie Some(true) => adapter_labeled && past_grace && !has_live_descendants, } } @@ -472,7 +482,12 @@ pub fn session_is_zombie(pid: Option, adapter_labeled: bool, spawned_ms_ago .any(|d| spt_store::proc::is_process_alive(*d)) }); let past_grace = Duration::from_millis(spawned_ms_ago) >= spawn_client_grace(); - zombie_verdict(wrapper_alive, adapter_labeled, has_live_descendants, past_grace) + zombie_verdict( + wrapper_alive, + adapter_labeled, + has_live_descendants, + past_grace, + ) } /// The RC-origin input-fence verdict (ADR-0044 decision 3, @@ -616,7 +631,11 @@ const INJECT_MISS_STRIKE_BUDGET: u32 = 3; /// invariant, not its exact length. fn inject_miss_strike_budget() -> u32 { match std::env::var("SPT_INJECT_MISS_STRIKE_BUDGET") { - Ok(n) => n.parse::().ok().filter(|b| *b >= 1).unwrap_or(INJECT_MISS_STRIKE_BUDGET), + Ok(n) => n + .parse::() + .ok() + .filter(|b| *b >= 1) + .unwrap_or(INJECT_MISS_STRIKE_BUDGET), Err(_) => INJECT_MISS_STRIKE_BUDGET, } } @@ -716,7 +735,11 @@ const INJECT_TEXT_CHUNK: usize = 256; fn inject_text_chunk() -> usize { match std::env::var("SPT_INJECT_TEXT_CHUNK") { - Ok(n) => n.parse::().ok().filter(|c| *c > 0).unwrap_or(INJECT_TEXT_CHUNK), + Ok(n) => n + .parse::() + .ok() + .filter(|c| *c > 0) + .unwrap_or(INJECT_TEXT_CHUNK), Err(_) => INJECT_TEXT_CHUNK, } } @@ -1580,9 +1603,14 @@ impl OutputLog { /// the bounded direct-write degrade the exit fan-out uses. // [impl->REQ-SEAL-NO-CEREMONY-SURFACE] fn ceremony_surface(&self) -> Option<(SyncSender, SharedSend, u64, bool)> { - self.controller - .as_ref() - .map(|c| (c.tx.clone(), Arc::clone(&c.send), c.send.id(), c.seal_ceremony)) + self.controller.as_ref().map(|c| { + ( + c.tx.clone(), + Arc::clone(&c.send), + c.send.id(), + c.seal_ceremony, + ) + }) } /// Stamp the client-declared seal-ceremony capability onto the CURRENT @@ -1654,9 +1682,7 @@ impl OutputLog { // attach, which is precisely what "bring the engine room up" means. // The TOTP gate is the other half of the same seat rule and lives at // the same door, for the same reason the locks do. - crate::attach::EngineRoomLock::Pass => { - return self.bringup_refusal(code, conn, ticket) - } + crate::attach::EngineRoomLock::Pass => return self.bringup_refusal(code, conn, ticket), crate::attach::EngineRoomLock::NoViewport => { "the engine room has no viewport — it is never watched, at any origin" } @@ -1699,12 +1725,7 @@ impl OutputLog { /// a workaround. // [impl->REQ-ER-BRINGUP-TOTP-GATE] // [impl->REQ-ER-BRINGUP-ATTEMPT-BOUND] - fn bringup_refusal( - &self, - code: Option<&str>, - conn: u64, - ticket: AdmitTicket, - ) -> SeatGate { + fn bringup_refusal(&self, code: Option<&str>, conn: u64, ticket: AdmitTicket) -> SeatGate { use spt_store::engineroom as er; // THE SEATED-CONNECTION EXEMPTION IS EVALUATED FIRST, BEFORE THE TICKET // (releases#203). The gate is spent once per admitted CONNECTION — the @@ -2097,7 +2118,9 @@ fn empower_home_for_bringup( } match spt_store::empower::grant_session(session_id, home_subnet) { Ok(()) => { - spt_proto::emit_line_err!("ENGINE_ROOM_ADMIN_BRINGUP_EMPOWERED:{home_subnet} session={session_id}"); + spt_proto::emit_line_err!( + "ENGINE_ROOM_ADMIN_BRINGUP_EMPOWERED:{home_subnet} session={session_id}" + ); Some(home_subnet.to_string()) } Err(e) => { @@ -2214,10 +2237,8 @@ fn present_engine_room_briefing() { // answer is not a zero, so it takes the promising arm exactly as before. The // predicate is also record-existence, NOT liveness, so a re-attach to a room // whose perch is merely idle can never false-fire it. - let record = spt_store::perch::resolve_info_file( - id, - spt_store::perch::ParentHint::Infer, - ); + let record = + spt_store::perch::resolve_info_file(id, spt_store::perch::ParentHint::Infer); if perch_record_absent(&record) { spt_proto::emit_line_err!( "ENGINE_ROOM_BRIEFING_UNPRESENTED:{id}: the engine room has NO perch \ @@ -2287,10 +2308,7 @@ fn present_engine_room_briefing() { fn sweep_stale_engine_room_briefings() { let id = spt_store::engineroom::ENGINE_ROOM_ID; let perch = spt_store::engineroom::engine_room_perch(); - match spt_store::spool::drop_undelivered_from_at( - &perch, - spt_store::briefing::BRIEFING_AUTHOR, - ) { + match spt_store::spool::drop_undelivered_from_at(&perch, spt_store::briefing::BRIEFING_AUTHOR) { Ok(0) => {} Ok(n) => spt_proto::emit_line_err!( "ENGINE_ROOM_BRIEFING_SWEPT:{id}: dropped {n} undelivered briefing(s) \ @@ -2549,7 +2567,13 @@ impl OutputLog { } } - fn become_controller(&mut self, sub: SharedSend, by: Option, from_seq: u64, attach_gen: u64) { + fn become_controller( + &mut self, + sub: SharedSend, + by: Option, + from_seq: u64, + attach_gen: u64, + ) { // Drop the prior controller sink first (its writer's live loop ends when // tx drops), and bump the generation so (a) an in-flight deadline-evict // for the old controller can't unseat this one and (b) a prior writer @@ -2567,7 +2591,11 @@ impl OutputLog { sub.describe(&format!( "controller session={} endpoint={} by={}", self.session_id, - if self.endpoint.is_empty() { "-" } else { &self.endpoint }, + if self.endpoint.is_empty() { + "-" + } else { + &self.endpoint + }, by.as_deref().unwrap_or("local") )); sub.lifecycle_event( @@ -2646,7 +2674,7 @@ impl OutputLog { // Default-false; the subscribe wrapper stamps the client-declared // capability after the ladder (REQ-SEAL-NO-CEREMONY-SURFACE). seal_ceremony: false, - }); + }); self.stamp_driven_by(); // The seat changed hands (or was filled): the incoming controller does // not inherit the outgoing one's authority. An equal-generation re-serve @@ -2830,7 +2858,11 @@ impl OutputLog { sub.describe(&format!( "viewer session={} endpoint={} vid={vid}", self.session_id, - if self.endpoint.is_empty() { "-" } else { &self.endpoint } + if self.endpoint.is_empty() { + "-" + } else { + &self.endpoint + } )); sub.lifecycle_event( "viewer-attach", @@ -2867,8 +2899,9 @@ impl OutputLog { let evicted = Arc::new(AtomicBool::new(false)); let writer_evicted = Arc::clone(&evicted); let session_id = self.session_id; - let writer = - thread::spawn(move || viewer_writer(writer_send, session_id, initial, rx, writer_evicted)); + let writer = thread::spawn(move || { + viewer_writer(writer_send, session_id, initial, rx, writer_evicted) + }); self.viewers.insert( vid, ViewerSink { @@ -2906,8 +2939,17 @@ impl OutputLog { gen: u64, code: Option, ) -> SubscribeOutcome { - self.resolve_subscribe_gated(sub, from_seq, intent, by, gen, code, AdmitTicket::None, false) - .0 + self.resolve_subscribe_gated( + sub, + from_seq, + intent, + by, + gen, + code, + AdmitTicket::None, + false, + ) + .0 } /// [`resolve_subscribe`](Self::resolve_subscribe) carrying the broker's @@ -2975,7 +3017,11 @@ impl OutputLog { "SUBSCRIBE_DECISION: session={} endpoint={} by={} conn={} intent={} \ old_by={} old_gen={} req_gen={} decision={}", self.session_id, - if self.endpoint.is_empty() { "-" } else { &self.endpoint }, + if self.endpoint.is_empty() { + "-" + } else { + &self.endpoint + }, by_lbl, conn, intent_lbl, @@ -3391,7 +3437,8 @@ impl OutputLog { self-healing partial view — strictly more consistent than raw \ delivery of the same overflow, and kept loud \ [REQ-RC-RESIZE-GEOMETRY-EPOCH][REQ-RC-RESIZE-PRESENTATION-BARRIER]", - self.session_id, t.dropped + self.session_id, + t.dropped ); } let mut at = t.from; @@ -3503,7 +3550,6 @@ impl OutputLog { } } - /// Stamp the perch's `driven_by` to the current controller's identity (the /// broker is the single writer — resolves the clear-race). The remote-drive /// detection fact (REQ-REACH-1) moved here from `serve_attach` so a displaced @@ -3690,7 +3736,10 @@ fn viewer_writer( fn drop(&mut self) { self.send.lifecycle_event( "writer-exit", - &format!("role=viewer session={} reason={}", self.session_id, self.reason), + &format!( + "role=viewer session={} reason={}", + self.session_id, self.reason + ), ); } } @@ -3960,7 +4009,10 @@ fn controller_writer( note_controller_write_retired(sid, send.id(), &e); send.lifecycle_event( "writer-exit", - &format!("role=controller session={sid} reason=write-failed kind={:?}", e.kind()), + &format!( + "role=controller session={sid} reason=write-failed kind={:?}", + e.kind() + ), ); return; } @@ -4002,7 +4054,10 @@ fn controller_writer( // [impl->REQ-CONN-POISON-ATTRIBUTION] send.lifecycle_event( "writer-exit", - &format!("role=controller session={sid} reason=write-failed kind={:?}", e.kind()), + &format!( + "role=controller session={sid} reason=write-failed kind={:?}", + e.kind() + ), ); return; } @@ -4297,7 +4352,6 @@ fn recover_log(m: &Mutex) -> std::sync::MutexGuard<'_, OutputLog> { } } - /// WHICH of the anchor subnet's two seeds admitted a bring-up code. /// /// A bool was enough until releases#102: an ADMIN-TOTP bring-up empowers the @@ -4366,10 +4420,7 @@ pub(crate) fn classify_cred(member_verified: bool, admin_verified: bool) -> Brin /// ceremony, and nothing here reaches the joiner-facing wire. // [impl->REQ-ER-BRINGUP-TOTP-GATE] // [impl->REQ-ENGINEROOM-ADMIN-BRINGUP-EMPOWERS] -fn bringup_code_verifies( - room: &spt_store::engineroom::EngineRoom, - presented: &str, -) -> BringUpCred { +fn bringup_code_verifies(room: &spt_store::engineroom::EngineRoom, presented: &str) -> BringUpCred { use spt_net::net::pairing::totp::code_matches_window; let subnets = spt_store::subnet::SubnetStore::load(); let Some(rec) = subnets.find(&room.home_subnet) else { @@ -4480,7 +4531,10 @@ impl MintOffers { /// No offers — the enroll-purpose ceremony's shape (it IS an enrollment; /// neither offer is meaningful on its overlay). fn none() -> MintOffers { - MintOffers { fido2: None, offer_enroll: false } + MintOffers { + fido2: None, + offer_enroll: false, + } } } @@ -4501,8 +4555,14 @@ fn compose_mint_offers(endpoint: &str, subnet: &str, content: &[u8], now: u64) - return MintOffers::none(); }; let node = spt_net::net::registry::key_prefix(&id.public_key().to_hex()); - if spt_store::enroll::EnrollStore::load().find(&node, subnet).is_none() { - return MintOffers { fido2: None, offer_enroll: true }; + if spt_store::enroll::EnrollStore::load() + .find(&node, subnet) + .is_none() + { + return MintOffers { + fido2: None, + offer_enroll: true, + }; } let minter = format!("{subnet}:{endpoint}@{node}"); let payload = spt_store::seal::fido2_signing_payload( @@ -4512,7 +4572,10 @@ fn compose_mint_offers(endpoint: &str, subnet: &str, content: &[u8], now: u64) - ); MintOffers { fido2: Some(( - Fido2Offer { minter, minted_at: now }, + Fido2Offer { + minter, + minted_at: now, + }, encode_bytes(&payload), node, )), @@ -6163,8 +6226,7 @@ impl Broker { // AND the off-lock converge_perch_stamps below see the // cleared state and the stale info.json stamp clears. let _ = log.reap_dead_controller(); - let stamp_gen = - stamp_slot(&endpoint).gen.load(Ordering::Acquire); + let stamp_gen = stamp_slot(&endpoint).gen.load(Ordering::Acquire); SessSnap { id, endpoint, @@ -6298,7 +6360,9 @@ impl Broker { for id in &my_cb_streams { let _ = host.send_stream(*id, &[], true); let _ = host.retire_stream_terminal(*id); - spt_proto::emit_line_err!("STREAM_CONNBOUND_RETIRE:{id}: opener conn exited — FIN + terminal retire"); + spt_proto::emit_line_err!( + "STREAM_CONNBOUND_RETIRE:{id}: opener conn exited — FIN + terminal retire" + ); } // And presence: the liveness log + its ring persist (D4c). if my_presence_sub { @@ -6328,7 +6392,11 @@ impl Broker { /// [`KIND_SPAWN_CONFLICT`] — NEVER `Spawned(existing)`. `Ok(None)` = the /// conflict was sent (no session to auto-subscribe). // [impl->REQ-SPAWN-FRESH-TRUTHFUL] - fn dispatch_spawn_fresh(&self, env: Envelope, send: &SharedSend) -> Result, String> { + fn dispatch_spawn_fresh( + &self, + env: Envelope, + send: &SharedSend, + ) -> Result, String> { let req: SpawnReq = serde_json::from_value(env.payload).map_err(|e| format!("bad spawn payload: {e}"))?; self.dispatch_spawn_policy(req, send, true) @@ -6435,7 +6503,9 @@ impl Broker { let adapters_dir = spt_store::perch::adapters_dir(); let (record, manifest) = match spt_runtime::registry::resolve_option(&adapters_dir, &room.adapter) { - Ok((r, m)) if m.adapter.kind == spt_runtime::manifest::AdapterKind::Harness => (r, m), + Ok((r, m)) if m.adapter.kind == spt_runtime::manifest::AdapterKind::Harness => { + (r, m) + } _ => { reply( BRING_UP_REFUSED, @@ -6530,7 +6600,8 @@ impl Broker { spt_proto::emit_line_err!( "ENGINE_ROOM_PERCH_ANCHORED:{}: skeleton created, home={} — the \ harness bind inherits this anchor", - req.endpoint, room.home_subnet + req.endpoint, + room.home_subnet ); } // Already there: the ordinary re-bring-up. Silent on purpose — a line @@ -6780,12 +6851,8 @@ impl Broker { // subnet is enrolled, the E shortcut when it is not — decided HERE so // the payload's minted_at is fixed before the open ships. // [impl->REQ-SEAL-CEREMONY-FIDO2] - let offers = compose_mint_offers( - &req.endpoint, - &req.subnet, - &content, - crate::brain::now_ms(), - ); + let offers = + compose_mint_offers(&req.endpoint, &req.subnet, &content, crate::brain::now_ms()); if let Err(detail) = self.open_ceremony_overlay( &req.endpoint, &req.subnet, @@ -7028,11 +7095,7 @@ impl Broker { /// replication apply arm (REQ-SEAL-CEREMONY-TOTP). // [impl->REQ-SEAL-CEREMONY-TOTP] // [impl->REQ-SEAL-CEREMONY-ESC-CANCEL] - fn dispatch_seal_ceremony_code( - &self, - env: Envelope, - send: &SharedSend, - ) -> Result<(), String> { + fn dispatch_seal_ceremony_code(&self, env: Envelope, send: &SharedSend) -> Result<(), String> { use spt_store::engineroom as er; let req: SealCeremonyCodeReq = serde_json::from_value(env.payload) .map_err(|e| format!("bad seal-ceremony-code payload: {e}"))?; @@ -7152,8 +7215,7 @@ impl Broker { return Ok(()); } // Verified: mint with the pinned spellings and end the ceremony. - let (outcome, detail, token) = - self.mint_ceremony_seal_fido2(req.ceremony_id, sig_hex); + let (outcome, detail, token) = self.mint_ceremony_seal_fido2(req.ceremony_id, sig_hex); self.end_ceremony(req.ceremony_id, outcome, detail, token); return Ok(()); } @@ -7328,8 +7390,7 @@ impl Broker { let minter = format!("{subnet}:{endpoint}@{node}"); let guard = crate::dispatch::seal_apply_lock(); let mut store = spt_store::seal::SealStore::load(); - let record = match spt_store::seal::mint_seal(&mut store, &content, &minter, "totp", now) - { + let record = match spt_store::seal::mint_seal(&mut store, &content, &minter, "totp", now) { Ok(r) => r, Err(e) => { drop(guard); @@ -7385,8 +7446,7 @@ impl Broker { let Some(f) = &p.fido2 else { return ( SEAL_CEREMONY_REFUSED, - "no FIDO2 offer is pinned on this ceremony — nothing was minted." - .to_string(), + "no FIDO2 offer is pinned on this ceremony — nothing was minted.".to_string(), None, ); }; @@ -7510,26 +7570,21 @@ impl Broker { } } let mut seal_store = spt_store::seal::SealStore::load(); - let record = match spt_store::seal::mint_seal( - &mut seal_store, - &content, - &minter, - "totp", - now, - ) { - Ok(r) => r, - Err(e) => { - drop(guard); - return ( - SEAL_CEREMONY_REFUSED, - format!( - "the mint refused: {e} — nothing was enrolled and nothing \ + let record = + match spt_store::seal::mint_seal(&mut seal_store, &content, &minter, "totp", now) { + Ok(r) => r, + Err(e) => { + drop(guard); + return ( + SEAL_CEREMONY_REFUSED, + format!( + "the mint refused: {e} — nothing was enrolled and nothing \ was minted." - ), - None, - ); - } - }; + ), + None, + ); + } + }; if let Err(e) = enroll_store.save() { drop(guard); return ( @@ -7545,7 +7600,8 @@ impl Broker { // Undo the just-persisted enrollment so the pair stays // both-or-neither. let mut undo = spt_store::enroll::EnrollStore::load(); - undo.records.retain(|r| !(r.node == node && r.subnet == subnet)); + undo.records + .retain(|r| !(r.node == node && r.subnet == subnet)); if let Err(undo_e) = undo.save() { spt_proto::emit_line_err!( "SEAL_E_HALF_STATE: ceremony={ceremony_id} — the seal store failed \ @@ -7668,14 +7724,18 @@ impl Broker { drop(guard); spt_proto::emit_line_err!( "SEAL_ENROLL_MINTED: ceremony={ceremony_id} node={node} subnet={} backend={}", - record.subnet, record.backend_kind + record.subnet, + record.backend_kind ); ( SEAL_CEREMONY_ADMITTED, format!( "{SEAL_ENROLLED}\npubkey_hex: {}\nnode: {}\nsubnet: {}\nenrolled_at: {}\n\ backend_kind: {}", - record.pubkey_hex, record.node, record.subnet, record.enrolled_at, + record.pubkey_hex, + record.node, + record.subnet, + record.enrolled_at, record.backend_kind ), None, @@ -7803,12 +7863,7 @@ impl Broker { /// than to sleep through it, and a sleeping test proves the TTL only for the /// value it slept for. // [impl->REQ-ER-BRINGUP-SPAWNS-SESSION] - fn mint_bringup_admit_at( - &self, - session: u64, - verdict: TicketVerdict, - now: Instant, - ) -> String { + fn mint_bringup_admit_at(&self, session: u64, verdict: TicketVerdict, now: Instant) -> String { let seed = spt_proto::identity::Identity::generate().seed(); let ticket = format!( "{BRING_UP_ADMIT_PREFIX}{}", @@ -7989,16 +8044,17 @@ impl Broker { let gate = { let sessions = recover(&self.sessions); let mut inflight = recover(&self.wake_inflight); - let live = sessions.iter().find(|(_, h)| h.endpoint == req.endpoint).map( - |(sid, h)| { + let live = sessions + .iter() + .find(|(_, h)| h.endpoint == req.endpoint) + .map(|(sid, h)| { ( *sid, h.session.process_id(), !h.adapter.is_empty(), h.spawned_at.elapsed().as_millis() as u64, ) - }, - ); + }); // The holder's own phase stamp, read under the SAME lock as the // claim — an elapsed against a recorded Instant, no I/O, per this // block's no-I/O-under-the-lock contract. @@ -8010,7 +8066,12 @@ impl Broker { WakeGate::AlreadyLive => { let (sid, spid, adapter_labeled, spawned_ms_ago) = live.expect("live is Some on AlreadyLive"); - Gate::AlreadyLive { sid, spid, adapter_labeled, spawned_ms_ago } + Gate::AlreadyLive { + sid, + spid, + adapter_labeled, + spawned_ms_ago, + } } WakeGate::Racing => Gate::Racing, WakeGate::Claim => { @@ -8055,7 +8116,12 @@ impl Broker { spawn_phase("gate_claimed", ""); break Some(guard); } - Gate::AlreadyLive { sid, spid, adapter_labeled, spawned_ms_ago } => { + Gate::AlreadyLive { + sid, + spid, + adapter_labeled, + spawned_ms_ago, + } => { // ONE liveness authority (ADR-0041 decision 6, // REQ-ENDPOINT-CYCLE-HONEST): before refusing/deduping by // citing the claimed session, PROBE its client tree — off @@ -8128,8 +8194,11 @@ impl Broker { ); let frame = Envelope::new( KIND_SPAWNED, - serde_json::to_value(Spawned { session_id: sid, pid: spid }) - .expect("Spawned serializes"), + serde_json::to_value(Spawned { + session_id: sid, + pid: spid, + }) + .expect("Spawned serializes"), ); send_frame(send, &frame); return Ok(Some(sid)); @@ -8459,18 +8528,15 @@ impl Broker { // C-1: the shared bounded-respawn give-up counter (starts at 0; the worker // resets it on a healthy commit, the dispatch respawn path increments it). let translation_respawns = Arc::new(AtomicU32::new(0)); - let translation = req - .translation_binary - .as_deref() - .and_then(|argv| { - build_translation( - argv, - &req.endpoint, - &input, - Arc::clone(&translation_respawns), - &log, - ) - }); + let translation = req.translation_binary.as_deref().and_then(|argv| { + build_translation( + argv, + &req.endpoint, + &input, + Arc::clone(&translation_respawns), + &log, + ) + }); spawn_phase("translation_ready", ""); @@ -8634,7 +8700,11 @@ impl Broker { let h = sessions .get(&req.session_id) .ok_or_else(|| format!("no such session {}", req.session_id))?; - (Arc::clone(&h.input), h.translation.clone(), Arc::clone(&h.log)) + ( + Arc::clone(&h.input), + h.translation.clone(), + Arc::clone(&h.log), + ) }; // RC-ORIGIN INPUT FENCE (ADR-0044 decision 3, the required defense): // an rc-tagged input must come from the ACTIVE controller lease's @@ -8775,7 +8845,9 @@ impl Broker { // recovered session shows clean; re-stamped if the new binary faults too). let perch = resolve_perch_path(endpoint, ParentHint::Infer); let _ = spt_store::info::set_translation_fault(&perch, None); - spt_proto::emit_line_err!("TRANSLATION_RESPAWN:{endpoint}: rebuilt faulted binary (attempt {n}/{budget})"); + spt_proto::emit_line_err!( + "TRANSLATION_RESPAWN:{endpoint}: rebuilt faulted binary (attempt {n}/{budget})" + ); } // Swap it in under the lock (the session may have exited mid-build). let mut map = recover(&self.sessions); @@ -8870,7 +8942,11 @@ impl Broker { "ENDPOINT_INJECT:{} ({} bytes → translation binary{})", req.endpoint, bytes.len(), - if req.native && !idle { ", native mid-active" } else { "" } + if req.native && !idle { + ", native mid-active" + } else { + "" + } ); send_frame( send, @@ -8895,20 +8971,29 @@ impl Broker { "ENDPOINT_INJECT:{}: endpoint ACTIVE -> spool (deferred hint), not injected", req.endpoint ); - send_frame(send, &endpoint_injected_envelope(&req.endpoint, false, true)); + send_frame( + send, + &endpoint_injected_envelope(&req.endpoint, false, true), + ); } else { spt_proto::emit_line_err!( "ENDPOINT_INJECT:{}: no working translation binary (absent/faulted/worker-gone) -> SPOOLED (idle window), not injected", req.endpoint ); - send_frame(send, &endpoint_injected_envelope(&req.endpoint, false, false)); + send_frame( + send, + &endpoint_injected_envelope(&req.endpoint, false, false), + ); } Ok(()) } // No hosted session for this endpoint — tell the caller to spool // NON-deferred (idle-eligible; a non-hosted target has no active window). None => { - send_frame(send, &endpoint_injected_envelope(&req.endpoint, false, false)); + send_frame( + send, + &endpoint_injected_envelope(&req.endpoint, false, false), + ); Ok(()) } } @@ -9037,8 +9122,10 @@ impl Broker { let supervised = crate::brainproc::supervised_generation(); let accepted = match serde_json::from_value::(env.payload) { Ok(a) if coordinator_announce_accepted(a.generation, supervised) => { - *self.coordinator_image.lock().expect("coordinator image lock") = - Some((a.generation, a.version)); + *self + .coordinator_image + .lock() + .expect("coordinator image lock") = Some((a.generation, a.version)); true } _ => false, @@ -9105,8 +9192,7 @@ impl Broker { }; let frame = Envelope::new( KIND_BRAIN_RESTARTED, - serde_json::to_value(BrainRestarted { honored }) - .expect("BrainRestarted serializes"), + serde_json::to_value(BrainRestarted { honored }).expect("BrainRestarted serializes"), ); send_frame(send, &frame); } @@ -9207,7 +9293,10 @@ impl Broker { .to_hex(); host.submit_dial(addr, remote_id_hex); // Immediate bare ack — the dial spawned; its outcome is a presence event. - send_frame(send, &Envelope::new(KIND_NET_DIAL_SUBMITTED, serde_json::Value::Null)); + send_frame( + send, + &Envelope::new(KIND_NET_DIAL_SUBMITTED, serde_json::Value::Null), + ); Ok(()) } @@ -9697,8 +9786,7 @@ impl Broker { sessions .iter() .find(|(id, h)| { - req.session_id == Some(**id) - || want_endpoint.is_some_and(|e| e == h.endpoint) + req.session_id == Some(**id) || want_endpoint.is_some_and(|e| e == h.endpoint) }) .map(|(_, h)| (h.session.process_id(), Arc::clone(&h.session))) }; @@ -9790,12 +9878,10 @@ impl Broker { &rec.name, ) .ok() - .and_then(|m| m.service) - else { + .and_then(|m| m.service) else { continue; }; - let outcome = - crate::servicehost::quiesce_for_update(set, &rec.name, &service); + let outcome = crate::servicehost::quiesce_for_update(set, &rec.name, &service); spt_proto::emit_line_err!("SERVICE_QUIESCE:{}: {outcome:?}", rec.name); if !outcome.clear_to_swap() { // Release every hold we took, including this one: an @@ -9964,15 +10050,30 @@ mod tests { #[test] fn stamp_divergence_gates_writes() { // Converged already → no writes. - assert_eq!(stamp_divergence(None, false, 0, None, false, 0), (false, false)); + assert_eq!( + stamp_divergence(None, false, 0, None, false, 0), + (false, false) + ); // The stamp-before-bind loss: perch says controlled=false, session IS driven. - assert_eq!(stamp_divergence(None, false, 0, None, true, 0), (true, false)); + assert_eq!( + stamp_divergence(None, false, 0, None, true, 0), + (true, false) + ); // A remote controller's driven_by appears → control write. - assert_eq!(stamp_divergence(None, true, 0, Some("n"), true, 0), (true, false)); + assert_eq!( + stamp_divergence(None, true, 0, Some("n"), true, 0), + (true, false) + ); // Viewer count changed only → viewer write only. - assert_eq!(stamp_divergence(None, true, 0, None, true, 2), (false, true)); + assert_eq!( + stamp_divergence(None, true, 0, None, true, 2), + (false, true) + ); // Both diverge. - assert_eq!(stamp_divergence(Some("a"), false, 1, None, true, 3), (true, true)); + assert_eq!( + stamp_divergence(Some("a"), false, 1, None, true, 3), + (true, true) + ); } // [unit->REQ-UPDATE-RUNNING-IMAGE-SURFACE] the coordinator-image @@ -10353,7 +10454,10 @@ mod tests { ); let ev: crate::msg::ViewerEvictedEvent = serde_json::from_value(env.payload).expect("marker payload"); - assert_eq!(ev.session_id, 7, "the marker names the evicted viewer's session"); + assert_eq!( + ev.session_id, 7, + "the marker names the evicted viewer's session" + ); } // ── NORMAL close: flag false → no marker; the client read hits EOF. ── @@ -10418,7 +10522,11 @@ mod tests { ); // First append fits the depth-1 queue (no overflow, not evicted yet). - assert_eq!(log.append(b"chunk-0"), None, "no controller; first chunk fits"); + assert_eq!( + log.append(b"chunk-0"), + None, + "no controller; first chunk fits" + ); assert!( !observed.load(Ordering::Acquire), "a viewer keeping within its queue is NOT flagged" @@ -10427,7 +10535,11 @@ mod tests { // Second append OVERFLOWS the (still-undrained) depth-1 queue → eviction: // the flag is SET (so the writer skips-to-live) and the sink is removed. - assert_eq!(log.append(b"chunk-1"), None, "no controller; eviction returns no ctrl job"); + assert_eq!( + log.append(b"chunk-1"), + None, + "no controller; eviction returns no ctrl job" + ); assert!( observed.load(Ordering::Acquire), "an overflow eviction must SET the sink's `evicted` flag BEFORE dropping \ @@ -10477,7 +10589,14 @@ mod tests { fn exit_enqueues_behind_queued_output_per_sink() { let (send, mut client, _recv) = controller_socket_pair(); let mut log = OutputLog::new(9, DEFAULT_LOG_CHUNKS, String::new(), (24, 80)); - let out = log.resolve_subscribe(Arc::clone(&send), 0, AttachIntent::Control, Some("op".into()), 200, None); + let out = log.resolve_subscribe( + Arc::clone(&send), + 0, + AttachIntent::Control, + Some("op".into()), + 200, + None, + ); assert!(matches!(out, SubscribeOutcome::Controller), "got {out:?}"); // Queue output THEN the Exit through the same fanout the exit waiter uses. @@ -10486,7 +10605,11 @@ mod tests { } let frame = Envelope::new( crate::msg::KIND_EXIT, - serde_json::to_value(ExitEvent { session_id: 9, code: Some(0) }).unwrap(), + serde_json::to_value(ExitEvent { + session_id: 9, + code: Some(0), + }) + .unwrap(), ); let fanout = log.exit_fanout(); let (tx, sink) = fanout.controller.expect("controller queue"); @@ -10523,17 +10646,34 @@ mod tests { let (taker, _cc, _rc2) = controller_socket_pair(); let mut log = OutputLog::new(1, DEFAULT_LOG_CHUNKS, String::new(), (24, 80)); - let out = log.resolve_subscribe(Arc::clone(&live), 0, AttachIntent::Control, Some("op".into()), 200, None); + let out = log.resolve_subscribe( + Arc::clone(&live), + 0, + AttachIntent::Control, + Some("op".into()), + 200, + None, + ); assert!(matches!(out, SubscribeOutcome::Controller), "got {out:?}"); // NEWER gen + plain Control → loud SUPERSESSION (the live replacement // viewport — the T6 shape): the slot moves; outcome is Controller. // (The revoked marker is CONSUMED by the exiting writer — emission is // proven by `revoked_incumbent_writer_emits_the_terminal_displaced`.) - let out = log.resolve_subscribe(Arc::clone(&ctrl2), 0, AttachIntent::Control, Some("op".into()), 300, None); + let out = log.resolve_subscribe( + Arc::clone(&ctrl2), + 0, + AttachIntent::Control, + Some("op".into()), + 300, + None, + ); assert!(matches!(out, SubscribeOutcome::Controller), "got {out:?}"); let c = log.controller.as_ref().expect("replacement holds the slot"); - assert!(Arc::ptr_eq(&c.send, &ctrl2), "the newer viewport superseded"); + assert!( + Arc::ptr_eq(&c.send, &ctrl2), + "the newer viewport superseded" + ); assert_eq!(c.attach_gen, 300); assert!(!log.is_controller(&live), "the fence moved with the slot"); @@ -10546,15 +10686,28 @@ mod tests { "older-gen {intent:?} must refuse busy, got {out:?}" ); } - let c = log.controller.as_ref().expect("incumbent survives the replays"); + let c = log + .controller + .as_ref() + .expect("incumbent survives the replays"); assert_eq!(c.attach_gen, 300); // NEWER gen + explicit Take → loud supersession, TookControl outcome. - let out = log.resolve_subscribe(Arc::clone(&taker), 0, AttachIntent::Take, Some("op".into()), 400, None); + let out = log.resolve_subscribe( + Arc::clone(&taker), + 0, + AttachIntent::Take, + Some("op".into()), + 400, + None, + ); assert!(matches!(out, SubscribeOutcome::TookControl), "got {out:?}"); let c = log.controller.as_ref().expect("taker holds the slot"); assert!(Arc::ptr_eq(&c.send, &taker)); - assert_eq!(c.attach_gen, 400, "the slot carries the taker's lease generation"); + assert_eq!( + c.attach_gen, 400, + "the slot carries the taker's lease generation" + ); // [unit->REQ-INPUT-CONTROLLER-FENCE] assert!(!log.is_controller(&ctrl2)); assert!(log.is_controller(&taker)); @@ -10575,16 +10728,35 @@ mod tests { // A real controller with a REAL writer thread (empty ring → empty // initial batch; the writer parks on its live queue). - let out = log.resolve_subscribe(Arc::clone(&a_send), 0, AttachIntent::Control, Some("op".into()), 200, None); + let out = log.resolve_subscribe( + Arc::clone(&a_send), + 0, + AttachIntent::Control, + Some("op".into()), + 200, + None, + ); assert!(matches!(out, SubscribeOutcome::Controller), "got {out:?}"); // Distinct-lease Take: the old sink drops (tx closes) and its writer // must write the terminal Displaced to A's conn on exit. - let out = log.resolve_subscribe(Arc::clone(&taker), 0, AttachIntent::Take, Some("op".into()), 300, None); + let out = log.resolve_subscribe( + Arc::clone(&taker), + 0, + AttachIntent::Take, + Some("op".into()), + 300, + None, + ); assert!(matches!(out, SubscribeOutcome::TookControl), "got {out:?}"); let env = read_frame(&mut a_client).expect("A's conn carries the terminal frame"); - assert_eq!(env.kind, crate::msg::KIND_DISPLACED, "terminal Displaced, got {}", env.kind); + assert_eq!( + env.kind, + crate::msg::KIND_DISPLACED, + "terminal Displaced, got {}", + env.kind + ); let ev: crate::msg::DisplacedEvent = serde_json::from_value(env.payload).expect("displaced payload"); assert_eq!(ev.session_id, 7); @@ -10640,17 +10812,16 @@ mod tests { // A VIEWER with a generous channel we CAN drain — to prove it stays fed. let (vsend, _vclient, _vrecv) = controller_socket_pair(); let (vtx, vrx) = sync_channel::(VIEWER_CHANNEL_DEPTH); - log.viewers - .insert( - 0, - ViewerSink { - tx: vtx, - send: vsend, - evicted: Arc::new(AtomicBool::new(false)), - _writer: thread::spawn(|| {}), - origin_node: None, - }, - ); + log.viewers.insert( + 0, + ViewerSink { + tx: vtx, + send: vsend, + evicted: Arc::new(AtomicBool::new(false)), + _writer: thread::spawn(|| {}), + origin_node: None, + }, + ); // Append 50 chunks. The controller channel (depth 2) fills after 2; every // further append DROPS (returns None — within the deadline, never evict) and @@ -10695,9 +10866,17 @@ mod tests { fn contiguous_advance_freezes_on_a_gap() { let dt = AtomicU64::new(0); contiguous_advance(&dt, 0); - assert_eq!(dt.load(Ordering::Acquire), 1, "seq 0 (== cursor) advances to 1"); + assert_eq!( + dt.load(Ordering::Acquire), + 1, + "seq 0 (== cursor) advances to 1" + ); contiguous_advance(&dt, 1); - assert_eq!(dt.load(Ordering::Acquire), 2, "contiguous seq 1 advances to 2"); + assert_eq!( + dt.load(Ordering::Acquire), + 2, + "contiguous seq 1 advances to 2" + ); // GAP: cursor is 2 but seq 5 arrives (3,4 dropped while Full). FREEZE at 2 — // a high-watermark jump to 6 would skip 3,4 on resume = a B2 violation. contiguous_advance(&dt, 5); @@ -10708,10 +10887,18 @@ mod tests { ); // Re-delivering the frozen seq (2, via ring replay) resumes contiguous advance. contiguous_advance(&dt, 2); - assert_eq!(dt.load(Ordering::Acquire), 3, "re-delivering the frozen seq resumes"); + assert_eq!( + dt.load(Ordering::Acquire), + 3, + "re-delivering the frozen seq resumes" + ); // A rewind re-send (seq < cursor) is a no-op. contiguous_advance(&dt, 0); - assert_eq!(dt.load(Ordering::Acquire), 3, "a rewind re-send cannot lower the cursor"); + assert_eq!( + dt.load(Ordering::Acquire), + 3, + "a rewind re-send cannot lower the cursor" + ); } /// W1 — `advance_delivered` moves the shared cursor monotonically (D4-1) via @@ -10789,15 +10976,18 @@ mod tests { // interleaved with single keystrokes. let inputs: Vec> = vec![ b"first".to_vec(), - b"\x03".to_vec(), // Ctrl-C + b"\x03".to_vec(), // Ctrl-C b"PASTE-BLOCK-AAAA".to_vec(), b"z".to_vec(), - b"\r".to_vec(), // Enter + b"\r".to_vec(), // Enter b"PASTE-BLOCK-BBBB".to_vec(), b"last".to_vec(), ]; for rec in &inputs { - assert!(w.enqueue(rec.clone()), "depth 256: every enqueue is accepted"); + assert!( + w.enqueue(rec.clone()), + "depth 256: every enqueue is accepted" + ); } // Close the FIFO so the drain loop terminates, then drain through the SOLE // writer exactly as `input_writer` does. @@ -10834,7 +11024,10 @@ mod tests { // The first DEPTH enqueues fit (accepted, no backpressure yet). for i in 0..DEPTH { - assert!(w.enqueue(vec![i as u8]), "enqueue {i} fits within the bound"); + assert!( + w.enqueue(vec![i as u8]), + "enqueue {i} fits within the bound" + ); } assert!( !w.backpressure.load(Ordering::Acquire), @@ -10854,7 +11047,10 @@ mod tests { ); // A second overflow while still saturated stays dropped + backpressured (the // stamp is rising-edge-only, but the STATE remains true — no flap to false). - assert!(!w.enqueue(b"OVERFLOW-2".to_vec()), "still dropping while full"); + assert!( + !w.enqueue(b"OVERFLOW-2".to_vec()), + "still dropping while full" + ); assert!( w.backpressure.load(Ordering::Acquire), "backpressure stays asserted while the queue remains saturated" @@ -10892,7 +11088,10 @@ mod tests { panic!("poison the inject floor"); }) .join(); - assert!(floor.is_poisoned(), "precondition: the floor mutex is poisoned"); + assert!( + floor.is_poisoned(), + "precondition: the floor mutex is poisoned" + ); // The fix: the recovered guard is fully usable — open() takes, is_held reads. lock_floor(&floor).open(); assert!( @@ -10919,12 +11118,23 @@ mod tests { panic!("poison the sessions map mid-attach"); }) .join(); - assert!(sessions.is_poisoned(), "precondition: the sessions mutex is poisoned"); + assert!( + sessions.is_poisoned(), + "precondition: the sessions mutex is poisoned" + ); // The fix: the recovered guard is fully usable — the prior row survives and a // NEW attach can still insert/look up (no permanent wedge). - assert_eq!(recover(&sessions).get(&7).copied(), Some(70), "prior state survives recovery"); + assert_eq!( + recover(&sessions).get(&7).copied(), + Some(70), + "prior state survives recovery" + ); recover(&sessions).insert(9, 90); - assert_eq!(recover(&sessions).get(&9).copied(), Some(90), "the next attach still opens"); + assert_eq!( + recover(&sessions).get(&9).copied(), + Some(90), + "the next attach still opens" + ); } /// The physical screen a FRESH client terminal shows after applying the log's @@ -10971,16 +11181,29 @@ mod tests { log.commit_resize(4, 10); let screen = repaint_screen(&log); - assert_eq!(log.grid.geometry(), (4, 10), "the grid lands on the new geometry"); + assert_eq!( + log.grid.geometry(), + (4, 10), + "the grid lands on the new geometry" + ); assert_eq!(log.size, (4, 10), "the stored letterbox size follows"); - assert_eq!(log.geometry_epoch, 1, "a committed resize opens a new epoch"); + assert_eq!( + log.geometry_epoch, 1, + "a committed resize opens a new epoch" + ); assert_eq!( screen[0], "ABCDEFGHIJ", "the old-geometry row is TRUNCATED by the resize, never re-wrapped" ); assert_eq!(screen[1], "", "…so nothing wrapped onto row 2"); - assert_eq!(screen[2], "0123456789", "the new-geometry write wraps at 10"); - assert_eq!(screen[3], "ABCDE", "…and its tail is on row 4, not truncated away"); + assert_eq!( + screen[2], "0123456789", + "the new-geometry write wraps at 10" + ); + assert_eq!( + screen[3], "ABCDE", + "…and its tail is on row 4, not truncated away" + ); } // [unit->REQ-RC-RESIZE-GEOMETRY-EPOCH] The GROW direction, where the rejected @@ -11024,11 +11247,25 @@ mod tests { log.abort_resize(); // the surface refused the resize let screen = repaint_screen(&log); - assert_eq!(log.grid.geometry(), (3, 20), "the grid stays at the old geometry"); - assert_eq!(log.size, (3, 20), "the stored size is not advanced by a refusal"); + assert_eq!( + log.grid.geometry(), + (3, 20), + "the grid stays at the old geometry" + ); + assert_eq!( + log.size, + (3, 20), + "the stored size is not advanced by a refusal" + ); assert_eq!(log.geometry_epoch, 0, "a refused resize opens NO epoch"); - assert_eq!(screen[0], "ABCDEFGHIJKLMNO", "held output replayed at the old width"); - assert_eq!(screen[1], "XY", "post-issue bytes belong to the old geometry too"); + assert_eq!( + screen[0], "ABCDEFGHIJKLMNO", + "held output replayed at the old width" + ); + assert_eq!( + screen[1], "XY", + "post-issue bytes belong to the old geometry too" + ); } // [unit->REQ-RC-RESIZE-GEOMETRY-EPOCH] The barrier is single-occupancy: a @@ -11046,8 +11283,11 @@ mod tests { ); log.mark_resize_issued(); log.commit_resize(3, 10); - assert!(log.begin_resize(3, 14).is_ok(), "the barrier reopens after the commit"); - } + assert!( + log.begin_resize(3, 14).is_ok(), + "the barrier reopens after the commit" + ); + } /// Poll the shared `delivered_through` cursor until it reaches `want` (the /// controller writer advances it asynchronously on each successful socket @@ -11141,7 +11381,10 @@ mod tests { baselines the watermark jump instead of reject-gapping it" ); let bytes = decode_bytes(&ev.data_b64).unwrap(); - assert!(bytes.starts_with(b"\x1b[?1049"), "synthesized repaint, not raw"); + assert!( + bytes.starts_with(b"\x1b[?1049"), + "synthesized repaint, not raw" + ); // LEG 3: one successful sync write advances the cursor-of-record past the // WHOLE suppressed range as-if-written. @@ -11236,11 +11479,17 @@ mod tests { let mut log = floor_rig(); let (send2, mut client2, _recv2) = controller_socket_pair(); let resume_from = log.delivered_through.load(Ordering::Acquire); - assert_eq!(resume_from, 1, "precondition: the detached cursor is below the floor"); + assert_eq!( + resume_from, 1, + "precondition: the detached cursor is below the floor" + ); log.become_controller(Arc::clone(&send2), None, resume_from, 0); let f = read_frame(&mut client2).expect("the resume initial frame"); let ev: crate::msg::OutputEvent = serde_json::from_value(f.payload).unwrap(); - assert_eq!(ev.seq, 2, "the repaint rides the watermark pseudo-seq (next_seq - 1)"); + assert_eq!( + ev.seq, 2, + "the repaint rides the watermark pseudo-seq (next_seq - 1)" + ); assert!(ev.sync, "the below-floor repaint batch rides the wire flag"); let bytes = decode_bytes(&ev.data_b64).unwrap(); assert!( @@ -11254,7 +11503,10 @@ mod tests { assert!(log.append(b"live-after-resume").is_none()); // seq 3 let f = read_frame(&mut client2).expect("the live frame after the repaint"); let ev: crate::msg::OutputEvent = serde_json::from_value(f.payload).unwrap(); - assert_eq!(ev.seq, 3, "live frames stream raw + in-order after the repaint"); + assert_eq!( + ev.seq, 3, + "live frames stream raw + in-order after the repaint" + ); log.clear_controller(); drop(log); } @@ -11272,7 +11524,10 @@ mod tests { let f = read_frame(&mut client2).expect("the at-floor resume frame"); let ev: crate::msg::OutputEvent = serde_json::from_value(f.payload).unwrap(); assert_eq!(ev.seq, 3); - assert!(!ev.sync, "a raw ring slice is UNFLAGGED — strict B2 semantics untouched"); + assert!( + !ev.sync, + "a raw ring slice is UNFLAGGED — strict B2 semantics untouched" + ); assert_eq!( decode_bytes(&ev.data_b64).unwrap(), b"after-commit-raw", @@ -11296,9 +11551,14 @@ mod tests { assert_eq!(f.kind, crate::msg::KIND_SIZE); let f = read_frame(&mut view_client).expect("viewer initial frame"); let ev: crate::msg::OutputEvent = serde_json::from_value(f.payload).unwrap(); - assert_eq!(ev.seq, 2, "below-floor viewer gets the repaint at the pseudo-seq"); + assert_eq!( + ev.seq, 2, + "below-floor viewer gets the repaint at the pseudo-seq" + ); assert!( - decode_bytes(&ev.data_b64).unwrap().starts_with(b"\x1b[?1049"), + decode_bytes(&ev.data_b64) + .unwrap() + .starts_with(b"\x1b[?1049"), "the synthesized repaint, not raw suppressed ring bytes" ); @@ -11344,14 +11604,29 @@ mod tests { let ev: crate::msg::OutputEvent = serde_json::from_value(f.payload).unwrap(); let bytes = decode_bytes(&ev.data_b64).unwrap(); let s = String::from_utf8_lossy(&bytes); - assert!(s.contains("\x1b]2;mid-window-title\x07"), "title change surfaces: {s:?}"); - assert!(s.contains("\x1b[?25l"), "cursor-visibility toggle surfaces: {s:?}"); + assert!( + s.contains("\x1b]2;mid-window-title\x07"), + "title change surfaces: {s:?}" + ); + assert!( + s.contains("\x1b[?25l"), + "cursor-visibility toggle surfaces: {s:?}" + ); // A CROSS-geometry commit resets the scroll region (grid resize // semantics, matching the client terminal's own reset on the letterbox // move) — the region CONTRACT still surfaces, as the explicit reset. - assert!(s.contains("\x1b[r"), "the region contract surfaces explicitly: {s:?}"); - assert!(s.contains("\x1b[?1049h"), "alt-screen switch surfaces: {s:?}"); - assert!(s.contains("ALT"), "window content surfaces at the target geometry: {s:?}"); + assert!( + s.contains("\x1b[r"), + "the region contract surfaces explicitly: {s:?}" + ); + assert!( + s.contains("\x1b[?1049h"), + "alt-screen switch surfaces: {s:?}" + ); + assert!( + s.contains("ALT"), + "window content surfaces at the target geometry: {s:?}" + ); drop(log); // A SAME-geometry transition (a SIGWINCH re-assert: begin/commit at the @@ -11363,7 +11638,8 @@ mod tests { log.add_viewer(Arc::clone(&view_send), 0, None); let _ = read_frame(&mut view_client).expect("initial size"); let _ = read_frame(&mut view_client).expect("initial repaint"); - log.begin_resize(4, 20).expect("same-geometry barrier closes"); + log.begin_resize(4, 20) + .expect("same-geometry barrier closes"); assert!(log.append(b"\x1b[1;3r").is_none()); log.mark_resize_issued(); log.commit_resize(4, 20); @@ -11413,8 +11689,14 @@ mod tests { "the deferred toggles flush INSIDE the sync frame, after the repaint, \ in emission order: {s:?}" ); - assert!(!s.contains("\x1b]8;"), "the hyperlink pair drops balanced: {s:?}"); - assert!(s.contains("LINK"), "the link TEXT still renders via the repaint: {s:?}"); + assert!( + !s.contains("\x1b]8;"), + "the hyperlink pair drops balanced: {s:?}" + ); + assert!( + s.contains("LINK"), + "the link TEXT still renders via the repaint: {s:?}" + ); drop(log); } @@ -11497,7 +11779,11 @@ mod tests { log.mark_resize_issued(); log.abort_resize(); // the surface refused the resize - assert_eq!(log.grid.geometry(), (3, 20), "abort: grid stays at the old geometry"); + assert_eq!( + log.grid.geometry(), + (3, 20), + "abort: grid stays at the old geometry" + ); assert_eq!(log.size, (3, 20), "abort: stored size untouched"); // Viewer: the FIRST post-abort frame is the sync frame — no `size` frame @@ -11562,7 +11848,10 @@ mod tests { OutputLog::new(1, DEFAULT_LOG_CHUNKS, "reaped".to_string(), (24, 80)).stamp_reaped(); let after = spt_store::info::read_info(&perch).unwrap(); - assert!(!after.controlled, "control stamps never outlive their session"); + assert!( + !after.controlled, + "control stamps never outlive their session" + ); assert_eq!(after.driven_by, None); assert_eq!( after.controllable, @@ -11593,9 +11882,18 @@ mod tests { torn.append(b"x"); // next_seq now 1, ring=[(0,x)] torn.ring.push_back((999, b"garbage".to_vec())); // back(999) >= next_seq(1) → torn let next_before = torn.next_seq; - assert!(torn.clamp_or_reset(), "a torn ring (last seq >= next_seq) is reset"); - assert!(torn.ring.is_empty(), "the torn ring is emptied — no garbage served"); - assert_eq!(torn.next_seq, next_before, "next_seq is preserved (cursors never rewind)"); + assert!( + torn.clamp_or_reset(), + "a torn ring (last seq >= next_seq) is reset" + ); + assert!( + torn.ring.is_empty(), + "the torn ring is emptied — no garbage served" + ); + assert_eq!( + torn.next_seq, next_before, + "next_seq is preserved (cursors never rewind)" + ); // Torn: over-cap ring (an interrupted prune). let mut over = OutputLog::new(3, 2, String::new(), (24, 80)); @@ -11625,8 +11923,14 @@ mod tests { .join(); assert!(log.is_poisoned(), "precondition: the log mutex is poisoned"); let g = recover_log(&log); - assert!(g.ring.is_empty(), "recover_log clamps the torn ring to empty on recovery"); - assert_eq!(g.next_seq, 1, "next_seq preserved through the poison-recover clamp"); + assert!( + g.ring.is_empty(), + "recover_log clamps the torn ring to empty on recovery" + ); + assert_eq!( + g.next_seq, 1, + "next_seq preserved through the poison-recover clamp" + ); } // [unit->REQ-TRANSLATE-COMMIT-MISS-TOLERANCE] C-1 respool-once / dead-letter: a @@ -11643,10 +11947,16 @@ mod tests { assert_eq!(note_miss_respool(&mut set, "env-A"), MissRespool::Respool); assert!(set.contains("env-A")); // Second miss of the SAME envelope → dead-letter, NOT respooled again. - assert_eq!(note_miss_respool(&mut set, "env-A"), MissRespool::DeadLetter); + assert_eq!( + note_miss_respool(&mut set, "env-A"), + MissRespool::DeadLetter + ); // A DIFFERENT envelope respools once on its own. assert_eq!(note_miss_respool(&mut set, "env-B"), MissRespool::Respool); - assert_eq!(note_miss_respool(&mut set, "env-B"), MissRespool::DeadLetter); + assert_eq!( + note_miss_respool(&mut set, "env-B"), + MissRespool::DeadLetter + ); // A committed envelope is forgotten → a later miss respools it afresh. set.remove("env-A"); assert_eq!(note_miss_respool(&mut set, "env-A"), MissRespool::Respool); @@ -11677,7 +11987,10 @@ mod tests { let payload = b"XLATE_OK line one\nline two\nline three"; // Full echo present → verified. let full_echo = b"prompt> XLATE_OK line one\nline two\nline three\n"; - assert!(echo_verified(payload, full_echo), "a fully-echoed head verifies"); + assert!( + echo_verified(payload, full_echo), + "a fully-echoed head verifies" + ); // Head swallowed: only a suffix echoed (the field bug — mid-word start). The // leading prefix is ABSENT → verify MISS. let tail_only = b"three\r\n"; // the ~322B suffix class, head gone @@ -11686,11 +11999,23 @@ mod tests { "a swallowed head (prefix absent from echo) fails verify — the head-loss tell" ); // A keys-only sequence types no echoable text → vacuously verified. - assert!(echo_verified(b"", b""), "empty payload is vacuously verified"); - assert!(echo_verified(b"", b"noise"), "empty payload verifies regardless of echo"); + assert!( + echo_verified(b"", b""), + "empty payload is vacuously verified" + ); + assert!( + echo_verified(b"", b"noise"), + "empty payload verifies regardless of echo" + ); // A short payload (below the prefix window) matches on its whole self. - assert!(echo_verified(b"hi", b"...hi..."), "a short payload matches whole"); - assert!(!echo_verified(b"hi", b"...ho..."), "a short payload absent → miss"); + assert!( + echo_verified(b"hi", b"...hi..."), + "a short payload matches whole" + ); + assert!( + !echo_verified(b"hi", b"...ho..."), + "a short payload absent → miss" + ); } // [unit->REQ-INJECT-MULTILINE-INTEGRITY] Layer 1 re-arm: the settle-gate must re-run @@ -11705,14 +12030,26 @@ mod tests { fn should_settle_rearms_on_observable_pty() { // Echoing/interactive PTY (probe observed → not unobservable): re-settle EVERY // delivery's first byte — this is the class the `/clear` head-swallow bites. - assert!(should_settle(1, false), "observable PTY re-settles before each delivery"); + assert!( + should_settle(1, false), + "observable PTY re-settles before each delivery" + ); // Non-echoing ConPTY (probe unobservable, latched): skip the steady-state settle — // no reader-reattach race, and settling would burn the full deadline every time. - assert!(!should_settle(1, true), "unobservable-probe PTY skips the steady-state settle"); + assert!( + !should_settle(1, true), + "unobservable-probe PTY skips the steady-state settle" + ); // A RE-DRIVE always settles regardless of the latch (only reached on a swallowed // head → readiness must be re-confirmed before retyping). - assert!(should_settle(2, true), "a re-drive settles even when the probe is unobservable"); - assert!(should_settle(2, false), "a re-drive settles on an observable PTY too"); + assert!( + should_settle(2, true), + "a re-drive settles even when the probe is unobservable" + ); + assert!( + should_settle(2, false), + "a re-drive settles on an observable PTY too" + ); } // [unit->REQ-INJECT-MULTILINE-INTEGRITY] the subslice search the head match rides: @@ -11723,9 +12060,18 @@ mod tests { assert!(contains_subslice(b"abcdef", b"cde")); assert!(contains_subslice(b"abcdef", b"abc")); assert!(contains_subslice(b"abcdef", b"def")); - assert!(!contains_subslice(b"abcdef", b"ce"), "non-contiguous is not a subslice"); - assert!(contains_subslice(b"abc", b""), "empty needle is vacuously present"); - assert!(!contains_subslice(b"ab", b"abc"), "needle longer than haystack is absent"); + assert!( + !contains_subslice(b"abcdef", b"ce"), + "non-contiguous is not a subslice" + ); + assert!( + contains_subslice(b"abc", b""), + "empty needle is vacuously present" + ); + assert!( + !contains_subslice(b"ab", b"abc"), + "needle longer than haystack is absent" + ); } // [unit->REQ-INJECT-MULTILINE-INTEGRITY] the output-log tap the settle-gate + @@ -11763,17 +12109,31 @@ mod tests { // Small: whole, single emit. let mut parts: Vec> = Vec::new(); chunk_text(b"small", 256, |p| parts.push(p.to_vec())); - assert_eq!(parts, vec![b"small".to_vec()], "a small payload is one whole write"); + assert_eq!( + parts, + vec![b"small".to_vec()], + "a small payload is one whole write" + ); // Large: split into ceil(len/chunk) ordered parts, reassembling exactly. let payload: Vec = (0..1000u16).map(|i| (i % 251) as u8).collect(); let chunk = 256; let mut got: Vec> = Vec::new(); chunk_text(&payload, chunk, |p| got.push(p.to_vec())); - assert_eq!(got.len(), 1000_usize.div_ceil(chunk), "ceil(len/chunk) parts"); - assert!(got.iter().take(got.len() - 1).all(|p| p.len() == chunk), "all but last are full"); + assert_eq!( + got.len(), + 1000_usize.div_ceil(chunk), + "ceil(len/chunk) parts" + ); + assert!( + got.iter().take(got.len() - 1).all(|p| p.len() == chunk), + "all but last are full" + ); let reassembled: Vec = got.concat(); - assert_eq!(reassembled, payload, "in-order reassembly is byte-identical — no head/tail loss"); + assert_eq!( + reassembled, payload, + "in-order reassembly is byte-identical — no head/tail loss" + ); } // [unit->REQ-HAZARD-INJECT-WORKER-POISON] B6 leg (ii): a PANIC inside the inject @@ -12072,8 +12432,14 @@ mod tests { let mut log = OutputLog::new(1, DEFAULT_LOG_CHUNKS, String::new(), (24, 80)); // Establish: conn A holds the lease at generation 500. - let (out, decision) = - log.resolve_subscribe_inner(Arc::clone(&a), 0, AttachIntent::Control, Some("op".into()), 500, None); + let (out, decision) = log.resolve_subscribe_inner( + Arc::clone(&a), + 0, + AttachIntent::Control, + Some("op".into()), + 500, + None, + ); assert!(matches!(out, SubscribeOutcome::Controller), "got {out:?}"); assert_eq!(decision, "controller"); let epoch_after_establish = log.controller_epoch.load(Ordering::Acquire); @@ -12082,12 +12448,30 @@ mod tests { // replayed. The seat is untouched: same sink, same generation, and the // controller EPOCH does not move (a bump is what stops the live writer // mid-batch, so an unchanged epoch IS "the writer was never disturbed"). - let (out, decision) = - log.resolve_subscribe_inner(Arc::clone(&a), 0, AttachIntent::Control, Some("op".into()), 500, None); - assert!(matches!(out, SubscribeOutcome::Controller), "the wire answer stays Controller (N-1 tolerant), got {out:?}"); - assert_eq!(decision, "idempotent", "the breadcrumb distinguishes reuse from replacement"); - let seat = log.controller.as_ref().expect("the seat survives its own replay"); - assert!(Arc::ptr_eq(&seat.send, &a), "the SAME sink is preserved — not a fresh one over a dropped writer"); + let (out, decision) = log.resolve_subscribe_inner( + Arc::clone(&a), + 0, + AttachIntent::Control, + Some("op".into()), + 500, + None, + ); + assert!( + matches!(out, SubscribeOutcome::Controller), + "the wire answer stays Controller (N-1 tolerant), got {out:?}" + ); + assert_eq!( + decision, "idempotent", + "the breadcrumb distinguishes reuse from replacement" + ); + let seat = log + .controller + .as_ref() + .expect("the seat survives its own replay"); + assert!( + Arc::ptr_eq(&seat.send, &a), + "the SAME sink is preserved — not a fresh one over a dropped writer" + ); assert_eq!(seat.attach_gen, 500); assert_eq!( log.controller_epoch.load(Ordering::Acquire), @@ -12097,25 +12481,49 @@ mod tests { // CELL 2 — a DIFFERENT conn at the same generation is the fix-6 successor: // today's silent swap must NOT regress into idempotence. - let (out, decision) = - log.resolve_subscribe_inner(Arc::clone(&b), 0, AttachIntent::Control, Some("op".into()), 500, None); + let (out, decision) = log.resolve_subscribe_inner( + Arc::clone(&b), + 0, + AttachIntent::Control, + Some("op".into()), + 500, + None, + ); assert!(matches!(out, SubscribeOutcome::Controller), "got {out:?}"); - assert_eq!(decision, "controller", "a different carrier is a re-serve, not a replay"); + assert_eq!( + decision, "controller", + "a different carrier is a re-serve, not a replay" + ); assert!( Arc::ptr_eq(&log.controller.as_ref().unwrap().send, &b), "the successor conn takes the seat (ADR-0038 fix 6)" ); // CELL 3 — strictly newer generation still supersedes loudly... - let (out, decision) = - log.resolve_subscribe_inner(Arc::clone(&a), 0, AttachIntent::Take, Some("op".into()), 900, None); + let (out, decision) = log.resolve_subscribe_inner( + Arc::clone(&a), + 0, + AttachIntent::Take, + Some("op".into()), + 900, + None, + ); assert!(matches!(out, SubscribeOutcome::TookControl), "got {out:?}"); assert_eq!(decision, "took"); // CELL 4 — ...and strictly older is still refused busy. - let (out, decision) = - log.resolve_subscribe_inner(Arc::clone(&b), 0, AttachIntent::Control, Some("op".into()), 500, None); - assert!(matches!(out, SubscribeOutcome::BusyControlled { .. }), "got {out:?}"); + let (out, decision) = log.resolve_subscribe_inner( + Arc::clone(&b), + 0, + AttachIntent::Control, + Some("op".into()), + 500, + None, + ); + assert!( + matches!(out, SubscribeOutcome::BusyControlled { .. }), + "got {out:?}" + ); assert_eq!(decision, "busy"); log.clear_controller(); @@ -12142,7 +12550,9 @@ mod tests { 0, AttachIntent::Control, Some("op".into()), - 700, None); + 700, + None, + ); assert!(matches!(out, SubscribeOutcome::Controller), "got {out:?}"); assert_eq!(decision, "controller"); @@ -12153,7 +12563,9 @@ mod tests { 12, AttachIntent::Control, Some("op".into()), - 700, None); + 700, + None, + ); assert!(matches!(out, SubscribeOutcome::Controller), "got {out:?}"); assert_eq!( decision, "controller", @@ -12164,7 +12576,11 @@ mod tests { 12, "and the seat records the floor it was re-established from" ); - assert_eq!(log.controller.as_ref().unwrap().attach_gen, 700, "the generation is preserved (fix 6)"); + assert_eq!( + log.controller.as_ref().unwrap().attach_gen, + 700, + "the generation is preserved (fix 6)" + ); log.clear_controller(); } @@ -12190,7 +12606,9 @@ mod tests { 0, AttachIntent::Control, Some("op".into()), - 200, None); + 200, + None, + ); assert!(matches!(out, SubscribeOutcome::Controller), "got {out:?}"); // A replayed stale Request (same identity, OLDER generation) is @@ -12200,13 +12618,18 @@ mod tests { 0, AttachIntent::Control, Some("op".into()), - 100, None); + 100, + None, + ); let SubscribeOutcome::BusyControlled { by } = out else { panic!("a stale same-identity generation must refuse busy, got {out:?}"); }; assert_eq!(by, "op"); let c = log.controller.as_ref().expect("incumbent survives"); - assert!(Arc::ptr_eq(&c.send, &live), "the newer controller keeps the slot"); + assert!( + Arc::ptr_eq(&c.send, &live), + "the newer controller keeps the slot" + ); assert_eq!(c.attach_gen, 200); // EQUAL generation = the same Request reconstructed (dispatcher @@ -12216,7 +12639,9 @@ mod tests { 0, AttachIntent::Control, Some("op".into()), - 200, None); + 200, + None, + ); assert!(matches!(out, SubscribeOutcome::Controller), "got {out:?}"); assert!(Arc::ptr_eq(&log.controller.as_ref().unwrap().send, &stale)); @@ -12227,8 +12652,13 @@ mod tests { 0, AttachIntent::Control, Some("op".into()), - 0, None); - assert!(matches!(out, SubscribeOutcome::Controller), "legacy gen 0 re-takes, got {out:?}"); + 0, + None, + ); + assert!( + matches!(out, SubscribeOutcome::Controller), + "legacy gen 0 re-takes, got {out:?}" + ); log.clear_controller(); } @@ -12258,7 +12688,9 @@ mod tests { 0, AttachIntent::Control, Some("op".into()), - 200, None); + 200, + None, + ); assert!(matches!(out, SubscribeOutcome::Controller), "got {out:?}"); // Mid-serve gap resume: the SAME worker re-subscribes from its floor @@ -12268,8 +12700,13 @@ mod tests { 3, AttachIntent::Control, Some("op".into()), - 200, None); - assert!(matches!(out, SubscribeOutcome::Controller), "resume re-takes, got {out:?}"); + 200, + None, + ); + assert!( + matches!(out, SubscribeOutcome::Controller), + "resume re-takes, got {out:?}" + ); assert_eq!( log.controller.as_ref().unwrap().attach_gen, 200, @@ -12282,7 +12719,9 @@ mod tests { 0, AttachIntent::Control, Some("op".into()), - 100, None); + 100, + None, + ); assert!( matches!(out, SubscribeOutcome::BusyControlled { .. }), "a stale replay must stay refused across the resume, got {out:?}" @@ -12325,12 +12764,18 @@ mod tests { // The matching generation releases normally. log.detach_if_gen(&send, Some(200)); - assert!(log.controller.is_none(), "the owning generation's release clears"); + assert!( + log.controller.is_none(), + "the owning generation's release clears" + ); // None (N-1 / conn cleanup) keeps ptr-identity behavior. log.become_controller(Arc::clone(&send), Some("op".into()), 0, 300); log.detach_if_gen(&send, None); - assert!(log.controller.is_none(), "gen-less detach keeps the legacy ptr clear"); + assert!( + log.controller.is_none(), + "gen-less detach keeps the legacy ptr clear" + ); } /// #6 CORE (REQ-BROKER-SCREEN-GRID, ADR-0031), the integrated broker seam: @@ -12366,7 +12811,11 @@ mod tests { // The initial batch is ONE output frame carrying the synthesized repaint. let frame = read_frame(&mut client).expect("a repaint frame on attach"); - assert_eq!(frame.kind, crate::msg::KIND_OUTPUT, "the initial batch is an output frame"); + assert_eq!( + frame.kind, + crate::msg::KIND_OUTPUT, + "the initial batch is an output frame" + ); let ev: crate::msg::OutputEvent = serde_json::from_value(frame.payload).expect("output payload"); let repaint = decode_bytes(&ev.data_b64).expect("repaint b64 decodes"); @@ -12442,13 +12891,19 @@ mod tests { let mut auth = avt::Vt::new(cols as usize, rows as usize); auth.feed_str(std::str::from_utf8(frame1).unwrap()); auth.feed_str(std::str::from_utf8(frame2).unwrap()); - let auth: Vec = auth.view().map(|l| l.text().trim_end().to_string()).collect(); + let auth: Vec = auth + .view() + .map(|l| l.text().trim_end().to_string()) + .collect(); // Candidate: what the attaching client's terminal actually shows. let mut seen = avt::Vt::new(cols as usize, rows as usize); seen.feed_str(std::str::from_utf8(&repaint).unwrap()); seen.feed_str(std::str::from_utf8(&diff).unwrap()); - let seen: Vec = seen.view().map(|l| l.text().trim_end().to_string()).collect(); + let seen: Vec = seen + .view() + .map(|l| l.text().trim_end().to_string()) + .collect(); assert_eq!( seen, auth, @@ -12485,7 +12940,10 @@ mod tests { } thread::sleep(Duration::from_millis(1)); } - assert!(writer.is_finished(), "precondition: the writer thread has exited"); + assert!( + writer.is_finished(), + "precondition: the writer thread has exited" + ); log.controller = Some(ControllerSink { attach_gen: 0, establish_from_seq: 0, @@ -12503,14 +12961,20 @@ mod tests { Some("remote-node"), "precondition: a stale remote controller is present" ); - assert!(log.reap_dead_controller(), "a dead-writer controller is reaped"); + assert!( + log.reap_dead_controller(), + "a dead-writer controller is reaped" + ); assert!(!log.has_controller(), "the controller slot is cleared"); assert_eq!( log.controller_by(), None, "controller_by is now honest (None) → converge_perch_stamps clears the stamp" ); - assert!(!log.reap_dead_controller(), "idempotent: nothing left to reap"); + assert!( + !log.reap_dead_controller(), + "idempotent: nothing left to reap" + ); } // [unit->REQ-DRIVEN-BY-OWN-NODE-NORMALIZE] own-node latch is TRUTHFUL (doyle @@ -12544,7 +13008,10 @@ mod tests { Some(own_hex.as_str()), "an own-node controller latches driven_by to its own hex (CONTEXT:386)" ); - assert!(after.controlled, "controlled stays true (any-controller truth)"); + assert!( + after.controlled, + "controlled stays true (any-controller truth)" + ); log.clear_controller(); // A remote hex latches identically. @@ -12760,7 +13227,10 @@ mod tests { // The successor's own drop does release it — the control, without which // this cell is equally satisfied by a `release_claim` that never removes. release_claim(&mut map, "e1", 2); - assert!(!map.contains_key("e1"), "a claim's own generation releases it"); + assert!( + !map.contains_key("e1"), + "a claim's own generation releases it" + ); // And a drop for an endpoint nobody holds is inert rather than a panic. release_claim(&mut map, "never-claimed", 7); @@ -12779,8 +13249,14 @@ mod tests { let before = STALL_EVICT_COUNT.load(Ordering::Relaxed); let (nsend, _nc, _nr) = controller_socket_pair(); - let outcome = - log.resolve_subscribe(nsend, 0, AttachIntent::Control, Some("newcomer".to_string()), 0, None); + let outcome = log.resolve_subscribe( + nsend, + 0, + AttachIntent::Control, + Some("newcomer".to_string()), + 0, + None, + ); assert_eq!( outcome, @@ -12809,7 +13285,11 @@ mod tests { "a blocked-past-deadline writer is reaped though it has not exited" ); assert!(!log.has_controller(), "the controller slot is cleared"); - assert_eq!(log.controller_by(), None, "driven_by truth is now honest (None)"); + assert_eq!( + log.controller_by(), + None, + "driven_by truth is now honest (None)" + ); } /// W3a endpoint selection (REQ-ADAPTER-LIVE-UPDATE, ADR-0025): from the @@ -12833,19 +13313,39 @@ mod tests { // sort+dedup, not just incidental ordering. let rows = vec![ // ep-b matches (sorts AFTER ep-a despite appearing first). - ("ep-b".to_string(), "claude-spt".to_string(), Some(dir_b.clone())), + ( + "ep-b".to_string(), + "claude-spt".to_string(), + Some(dir_b.clone()), + ), // ep-a, two sessions, SAME endpoint+dir → must dedup to one entry. - ("ep-a".to_string(), "claude-spt".to_string(), Some(dir_a.clone())), - ("ep-a".to_string(), "claude-spt".to_string(), Some(dir_a.clone())), + ( + "ep-a".to_string(), + "claude-spt".to_string(), + Some(dir_a.clone()), + ), + ( + "ep-a".to_string(), + "claude-spt".to_string(), + Some(dir_a.clone()), + ), // Non-matching adapter → excluded entirely. - ("ep-c".to_string(), "codex-spt".to_string(), Some(PathBuf::from("/install/ep-c"))), + ( + "ep-c".to_string(), + "codex-spt".to_string(), + Some(PathBuf::from("/install/ep-c")), + ), // Matching adapter but NO install_dir → excluded (nothing to swap). ("ep-d".to_string(), "claude-spt".to_string(), None), // PROFILE-COMPOSITE row (F015B): a `--adapter claude-spt:ccs` endpoint // stores the composite `claude-spt:ccs`, but the update carries the // PARENT record name `claude-spt` — it MUST match on the parent (an // exact-match skew is the silent-no-op bug). - ("ep-e".to_string(), "claude-spt:ccs".to_string(), Some(dir_e.clone())), + ( + "ep-e".to_string(), + "claude-spt:ccs".to_string(), + Some(dir_e.clone()), + ), ]; let got = select_endpoints_running_adapter(rows, "claude-spt"); @@ -13086,8 +13586,16 @@ mod tests { let _ = spt_store::empower::drop_all(sid); let mut log = engine_room_log(); let (sub, _c, _r) = controller_socket_pair(); - let (out, note) = - log.resolve_subscribe_gated(sub, 0, AttachIntent::Control, None, 100, Some(member), AdmitTicket::None, false); + let (out, note) = log.resolve_subscribe_gated( + sub, + 0, + AttachIntent::Control, + None, + 100, + Some(member), + AdmitTicket::None, + false, + ); assert!( matches!(out, SubscribeOutcome::Controller), "the member code still takes the controls, got {out:?}" @@ -13114,8 +13622,16 @@ mod tests { let _ = spt_store::empower::drop_all(sid); let mut log = engine_room_log(); let (sub, _c, _r) = controller_socket_pair(); - let (out, note) = - log.resolve_subscribe_gated(sub, 0, AttachIntent::Control, None, 100, Some(admin.clone()), AdmitTicket::None, false); + let (out, note) = log.resolve_subscribe_gated( + sub, + 0, + AttachIntent::Control, + None, + 100, + Some(admin.clone()), + AdmitTicket::None, + false, + ); assert!( matches!(out, SubscribeOutcome::Controller), "the admin code takes the controls, got {out:?}" @@ -13163,10 +13679,21 @@ mod tests { let mut log = engine_room_log(); let (sub, _c, _r) = controller_socket_pair(); - let (out, note) = - log.resolve_subscribe_gated(sub, 0, AttachIntent::Take, None, 100, Some(admin), AdmitTicket::None, false); + let (out, note) = log.resolve_subscribe_gated( + sub, + 0, + AttachIntent::Take, + None, + 100, + Some(admin), + AdmitTicket::None, + false, + ); assert!( - matches!(out, SubscribeOutcome::Controller | SubscribeOutcome::TookControl), + matches!( + out, + SubscribeOutcome::Controller | SubscribeOutcome::TookControl + ), "the take is seated, got {out:?}" ); assert!( @@ -13346,8 +13873,16 @@ mod tests { let redeemed = broker.redeem_bringup_admit(Some(&live), 1); let mut log = engine_room_log(); let (sub, _c, _r) = controller_socket_pair(); - let (out, note) = - log.resolve_subscribe_gated(sub, 0, AttachIntent::Control, None, 100, None, redeemed, false); + let (out, note) = log.resolve_subscribe_gated( + sub, + 0, + AttachIntent::Control, + None, + 100, + None, + redeemed, + false, + ); assert!( matches!(out, SubscribeOutcome::Controller), "the seat resolves, got {out:?}" @@ -13439,7 +13974,14 @@ mod tests { clear_bringup_ledger(); let mut log = engine_room_log(); let (sub, _c, _r) = controller_socket_pair(); - let out = log.resolve_subscribe(sub, 0, AttachIntent::Control, None, 100, Some(member.clone())); + let out = log.resolve_subscribe( + sub, + 0, + AttachIntent::Control, + None, + 100, + Some(member.clone()), + ); assert!( matches!(out, SubscribeOutcome::Controller), "a member code brings the engine room up, got {out:?}" @@ -13453,8 +13995,7 @@ mod tests { assert_eq!(briefed.len(), 1, "exactly one briefing, got {briefed:?}"); assert_eq!(briefed[0].from, spt_store::briefing::BRIEFING_AUTHOR); assert!( - briefed[0].body.contains("Posture right now") - && briefed[0].body.contains("SCOPE"), + briefed[0].body.contains("Posture right now") && briefed[0].body.contains("SCOPE"), "carrying the posture and the ruleset table: {}", briefed[0].body ); @@ -13476,8 +14017,13 @@ mod tests { clear_bringup_ledger(); let mut log = engine_room_log(); let (sub, _c, _r) = controller_socket_pair(); - let wrong = if member == "000000" { "111111" } else { "000000" }; - let out = log.resolve_subscribe(sub, 0, AttachIntent::Control, None, 100, Some(wrong.into())); + let wrong = if member == "000000" { + "111111" + } else { + "000000" + }; + let out = + log.resolve_subscribe(sub, 0, AttachIntent::Control, None, 100, Some(wrong.into())); assert!( matches!(out, SubscribeOutcome::BusyControlled { .. }), "a wrong code takes nothing, got {out:?}" @@ -13490,7 +14036,14 @@ mod tests { ); let mut log = engine_room_log(); let (sub, _c, _r) = controller_socket_pair(); - let out = log.resolve_subscribe(sub, 0, AttachIntent::Control, None, 100, Some(member.clone())); + let out = log.resolve_subscribe( + sub, + 0, + AttachIntent::Control, + None, + 100, + Some(member.clone()), + ); assert!( matches!(out, SubscribeOutcome::BusyControlled { .. }), "the right code inside the backoff is refused like any other, got {out:?}" @@ -13609,14 +14162,8 @@ mod tests { // ── SEAT 2 on the SAME log: the #164 rescue must be untouched. ── clear_bringup_ledger(); let (sub2, _c2, _r2) = controller_socket_pair(); - let second = log.resolve_subscribe( - sub2, - 0, - AttachIntent::Control, - None, - 101, - Some(member), - ); + let second = + log.resolve_subscribe(sub2, 0, AttachIntent::Control, None, 101, Some(member)); let after_second = briefings(); let others: Vec = rows() .into_iter() @@ -13629,7 +14176,10 @@ mod tests { "PRECONDITION: the first code must seat the engine room, got {first:?}" ); assert!( - matches!(second, SubscribeOutcome::Controller | SubscribeOutcome::TookControl), + matches!( + second, + SubscribeOutcome::Controller | SubscribeOutcome::TookControl + ), "PRECONDITION: the second attach must take the seat, got {second:?}" ); @@ -13744,16 +14294,28 @@ mod tests { clear_bringup_ledger(); let mut log = engine_room_log(); let (sub, _c, _r) = controller_socket_pair(); - let first = - log.resolve_subscribe(sub, 0, AttachIntent::Control, None, 100, Some(member.clone())); + let first = log.resolve_subscribe( + sub, + 0, + AttachIntent::Control, + None, + 100, + Some(member.clone()), + ); let after_first = briefings(); // ── SEAT 2: the SAME session, a new connection, a new attach // generation — the re-attach a human makes. clear_bringup_ledger(); let (sub2, _c2, _r2) = controller_socket_pair(); - let second = - log.resolve_subscribe(sub2, 0, AttachIntent::Control, None, 101, Some(member.clone())); + let second = log.resolve_subscribe( + sub2, + 0, + AttachIntent::Control, + None, + 101, + Some(member.clone()), + ); let after_second = briefings(); // ── A FRESH SESSION: a new log is a newly hosted session. ── @@ -13842,8 +14404,11 @@ mod tests { std::process::id(), SEQ.fetch_add(1, Ordering::Relaxed) ); - Broker::bind_in(&name, spt_store::perch::spt_home().join("admit-effects.log")) - .expect("bind admit test broker") + Broker::bind_in( + &name, + spt_store::perch::spt_home().join("admit-effects.log"), + ) + .expect("bind admit test broker") } /// Read the `subscribed` verdict off a connection, skipping the output @@ -13976,7 +14541,11 @@ mod tests { // longer redeem, so a broker that has admitted bring-ups for months // holds only what is still live. let expired_by_now = broker.mint_bringup_admit_at(13, mechanics_verdict(), t0); - let live = broker.mint_bringup_admit_at(13, mechanics_verdict(), t0 + BRINGUP_ADMIT_TTL + Duration::from_secs(1)); + let live = broker.mint_bringup_admit_at( + 13, + mechanics_verdict(), + t0 + BRINGUP_ADMIT_TTL + Duration::from_secs(1), + ); let held = recover(&broker.bringup_admits); assert!( held.contains_key(&live) && !held.contains_key(&expired_by_now), @@ -14053,7 +14622,11 @@ mod tests { // way the admit mint does — a broker up for months holds only what is // still in flight. broker.note_bringup_in_flight_at("stale-endpoint", ready_wait, t0); - broker.note_bringup_in_flight_at(er, ready_wait, t0 + ready_wait + Duration::from_secs(1)); + broker.note_bringup_in_flight_at( + er, + ready_wait, + t0 + ready_wait + Duration::from_secs(1), + ); let held = recover(&broker.bringups_in_flight); assert!( held.contains_key(er) && !held.contains_key("stale-endpoint"), @@ -14339,7 +14912,10 @@ mod tests { // The four distinct ways a ticket-shaped string fails to redeem. let spent = broker.mint_bringup_admit(1, mechanics_verdict()); - assert_eq!(broker.redeem_bringup_admit(Some(&spent), 1), AdmitTicket::Redeemed(mechanics_verdict())); + assert_eq!( + broker.redeem_bringup_admit(Some(&spent), 1), + AdmitTicket::Redeemed(mechanics_verdict()) + ); let wrong_session = broker.mint_bringup_admit(1, mechanics_verdict()); let expired = broker.mint_bringup_admit_at(1, mechanics_verdict(), t0); let causes: [(&str, AdmitTicket); 4] = [ @@ -14347,7 +14923,10 @@ mod tests { "never minted", broker.redeem_bringup_admit(Some("admit:0123456789abcdef"), 1), ), - ("already spent", broker.redeem_bringup_admit(Some(&spent), 1)), + ( + "already spent", + broker.redeem_bringup_admit(Some(&spent), 1), + ), ( "wrong session", broker.redeem_bringup_admit(Some(&wrong_session), 42), @@ -14389,7 +14968,10 @@ mod tests { ); } assert_eq!( - sentences.iter().collect::>().len(), + sentences + .iter() + .collect::>() + .len(), 1, "one sentence for all four causes — the refusal must not say which, \ or it reports whether a bring-up is in flight: {sentences:?}" @@ -14650,8 +15232,11 @@ mod tests { crate::test_home::with_home(|_| { let (member, admin) = provision_engine_room(); let name = format!("spt-daemon-er-grant-{}.sock", std::process::id()); - let broker = Broker::bind_in(&name, spt_store::perch::spt_home().join("grant-effects.log")) - .expect("bind serving broker"); + let broker = Broker::bind_in( + &name, + spt_store::perch::spt_home().join("grant-effects.log"), + ) + .expect("bind serving broker"); let serving = Arc::clone(&broker); std::thread::spawn(move || { let _ = serving.serve(); @@ -14671,7 +15256,9 @@ mod tests { // (a) MEMBER code: comes up, grants nothing, claims nothing. clear_bringup_ledger(); let (asked_on, mut client, _r) = controller_socket_pair(); - broker.dispatch_bring_up(bring_up(&member), &asked_on).expect("the verb answers"); + broker + .dispatch_bring_up(bring_up(&member), &asked_on) + .expect("the verb answers"); let reply = brought_up_reply(&mut client); assert_eq!(reply.outcome, BRING_UP_ADMITTED, "{}", reply.detail); assert!( @@ -14698,7 +15285,9 @@ mod tests { // holding the controls would be a sentence that can turn out false. clear_bringup_ledger(); let (asked_on, mut client, _r) = controller_socket_pair(); - broker.dispatch_bring_up(bring_up(&admin), &asked_on).expect("the verb answers"); + broker + .dispatch_bring_up(bring_up(&admin), &asked_on) + .expect("the verb answers"); let reply = brought_up_reply(&mut client); assert_eq!(reply.outcome, BRING_UP_ADMITTED, "{}", reply.detail); assert!( @@ -14792,8 +15381,9 @@ mod tests { clear_bringup_ledger(); let ledger_file = spt_store::perch::engine_room_gate_file(); let name = format!("spt-daemon-er-e2e-{}.sock", std::process::id()); - let broker = Broker::bind_in(&name, spt_store::perch::spt_home().join("e2e-effects.log")) - .expect("bind serving broker"); + let broker = + Broker::bind_in(&name, spt_store::perch::spt_home().join("e2e-effects.log")) + .expect("bind serving broker"); let serving = Arc::clone(&broker); // The spawn dials this broker as a CLIENT (harnesshost → // Brain::cold_start), so the accept loop has to be up for the @@ -14921,7 +15511,10 @@ mod tests { .expect("the verb answers"); let again = brought_up_reply(&mut asked_client); assert_eq!(again.outcome, BRING_UP_ALREADY_LIVE, "{}", again.detail); - assert_eq!(again.session_id, sid, "naming the session already hosting it"); + assert_eq!( + again.session_id, sid, + "naming the session already hosting it" + ); assert!( again.admit.is_none(), "no ticket: this caller brought nothing up, and the seat gate still \ @@ -14962,7 +15555,8 @@ mod tests { for by in [None, Some("PEERHEX".to_string())] { let mut log = engine_room_log(); let (sub, _c, _r) = controller_socket_pair(); - let out = log.resolve_subscribe(sub, 0, AttachIntent::Viewer, by.clone(), 100, None); + let out = + log.resolve_subscribe(sub, 0, AttachIntent::Viewer, by.clone(), 100, None); assert!( matches!(out, SubscribeOutcome::BusyControlled { .. }), "the engine room is never watched (by={by:?}), got {out:?}" @@ -14991,8 +15585,7 @@ mod tests { clear_bringup_ledger(); let mut log = engine_room_log(); let (sub, _c, _r) = controller_socket_pair(); - let out = - log.resolve_subscribe(sub, 0, intent, None, 100, Some(member.clone())); + let out = log.resolve_subscribe(sub, 0, intent, None, 100, Some(member.clone())); assert!( matches!(out, SubscribeOutcome::Controller), "local {intent:?} takes the controls, got {out:?}" @@ -15022,13 +15615,8 @@ mod tests { let id = spt_store::engineroom::ENGINE_ROOM_ID; let perch = resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&perch).unwrap(); - let rec = spt_store::info::InfoJson::new( - id, - "t", - std::process::id(), - "sid-1", - "live_agent", - ); + let rec = + spt_store::info::InfoJson::new(id, "t", std::process::id(), "sid-1", "live_agent"); spt_store::info::write_info(&perch, &rec).unwrap(); let empower = |subnet: &str| { let mut held = spt_store::empower::Empowerments::default(); @@ -15260,10 +15848,19 @@ mod tests { fn seal_codes_verify_member_or_admin_and_nothing_else() { crate::test_home::with_home(|_| { let (member, admin) = provision_seal_subnet("sealnet"); - assert!(seal_code_verifies("sealnet", &member), "a member code admits"); - assert!(seal_code_verifies("sealnet", &admin), "an admin code admits"); + assert!( + seal_code_verifies("sealnet", &member), + "a member code admits" + ); + assert!( + seal_code_verifies("sealnet", &admin), + "an admin code admits" + ); let wrong = wrong_code_beside(&member, &admin); - assert!(!seal_code_verifies("sealnet", &wrong), "a wrong code refuses"); + assert!( + !seal_code_verifies("sealnet", &wrong), + "a wrong code refuses" + ); assert!( !seal_code_verifies("no-such-subnet", &member), "a subnet with no local key material verifies nothing" @@ -15300,7 +15897,10 @@ mod tests { #[test] fn the_ceremony_surface_is_the_seat_table_and_the_stamp_is_conn_keyed() { let mut log = engine_room_log(); - assert!(log.ceremony_surface().is_none(), "no controller, no surface"); + assert!( + log.ceremony_surface().is_none(), + "no controller, no surface" + ); let (sub, _client, _r) = controller_socket_pair(); let conn = sub.id(); @@ -15313,7 +15913,10 @@ mod tests { log.stamp_controller_seal_ceremony(conn + 1, true); assert!(!log.ceremony_surface().unwrap().3, "wrong conn, no stamp"); log.stamp_controller_seal_ceremony(conn, true); - assert!(log.ceremony_surface().unwrap().3, "the declaring conn stamps"); + assert!( + log.ceremony_surface().unwrap().3, + "the declaring conn stamps" + ); log.clear_controller(); assert!( @@ -15345,7 +15948,11 @@ mod tests { .unwrap(); let r = seal_reply(&mut req_client); assert_eq!(r.outcome, SEAL_CEREMONY_REFUSED); - assert!(r.detail.starts_with(SEAL_CEREMONY_CONTENT_TOO_LONG), "{}", r.detail); + assert!( + r.detail.starts_with(SEAL_CEREMONY_CONTENT_TOO_LONG), + "{}", + r.detail + ); // EXACTLY 500 MULTI-BYTE scalars (1500 bytes): passes the cap — // the next refusal in the ladder is the no-surface one, which is @@ -15373,7 +15980,11 @@ mod tests { ) .unwrap(); let r = seal_reply(&mut req_client); - assert!(r.detail.starts_with(SEAL_CEREMONY_CONTENT_NOT_UTF8), "{}", r.detail); + assert!( + r.detail.starts_with(SEAL_CEREMONY_CONTENT_NOT_UTF8), + "{}", + r.detail + ); }); } @@ -15468,7 +16079,7 @@ mod tests { &old_send, ) .unwrap(); - let seated = read_subscribed_reply(&mut old_client); + let seated = read_subscribed_reply(&mut old_client); assert!(matches!(seated.outcome, SubscribeOutcome::Controller)); broker .dispatch_seal_ceremony(seal_ceremony_env("ling", "sealnet", b"content"), &req_send) @@ -15509,10 +16120,7 @@ mod tests { SubscribeOutcome::Controller | SubscribeOutcome::TookControl )); broker - .dispatch_seal_ceremony( - seal_ceremony_env("ling", "sealnet", b"seal me"), - &req_send, - ) + .dispatch_seal_ceremony(seal_ceremony_env("ling", "sealnet", b"seal me"), &req_send) .unwrap(); let open = loop { let env = read_frame(&mut cap_client).expect("the overlay open reaches the seat"); @@ -15530,7 +16138,10 @@ mod tests { // SIGNET W2: the offer decision rides the open — this home holds // no enrollment, so the E offer is stamped and no FIDO2 fields. // [unit->REQ-SEAL-ENROLL-SHORTCUT-E] - assert!(open.offer_enroll, "an un-enrolled pair's open stamps the E offer"); + assert!( + open.offer_enroll, + "an un-enrolled pair's open stamps the E offer" + ); assert!(open.payload_to_sign_b64.is_none()); assert!(open.fido2_node.is_none()); assert_eq!( @@ -15580,7 +16191,10 @@ mod tests { assert!(r.token.is_none(), "an enrollment mints no token"); assert!(r.detail.starts_with(SEAL_ENROLLED), "{}", r.detail); let node = spt_net::net::registry::key_prefix( - &spt_store::nodeid::load_or_create().unwrap().public_key().to_hex(), + &spt_store::nodeid::load_or_create() + .unwrap() + .public_key() + .to_hex(), ); let store = spt_store::enroll::EnrollStore::load(); let rec = store.find(&node, "sealnet").expect("the record PERSISTED"); @@ -15600,7 +16214,11 @@ mod tests { .unwrap(); let r = seal_reply(&mut req_client); assert_eq!(r.outcome, SEAL_CEREMONY_REFUSED); - assert!(r.detail.starts_with(SEAL_ENROLL_ALREADY_ENROLLED), "{}", r.detail); + assert!( + r.detail.starts_with(SEAL_ENROLL_ALREADY_ENROLLED), + "{}", + r.detail + ); assert_eq!( spt_store::enroll::EnrollStore::load() .find(&node, "sealnet") @@ -15640,7 +16258,10 @@ mod tests { /// the daemon boot path's posture). fn own_node_short_hex() -> String { spt_net::net::registry::key_prefix( - &spt_store::nodeid::load_or_create().unwrap().public_key().to_hex(), + &spt_store::nodeid::load_or_create() + .unwrap() + .public_key() + .to_hex(), ) } @@ -15649,8 +16270,15 @@ mod tests { fn enroll_own_node(subnet: &str, pubkey_hex: &str) -> String { let node = own_node_short_hex(); let mut es = spt_store::enroll::EnrollStore::load(); - spt_store::enroll::mint_enrollment(&mut es, pubkey_hex, &node, subnet, "hello-kcm-rs256", 1) - .unwrap(); + spt_store::enroll::mint_enrollment( + &mut es, + pubkey_hex, + &node, + subnet, + "hello-kcm-rs256", + 1, + ) + .unwrap(); es.save().unwrap(); node } @@ -15674,9 +16302,11 @@ mod tests { let node = enroll_own_node("sealnet", "aabb"); let offers = compose_mint_offers("ling", "sealnet", b"seal me", 42_000); assert!(!offers.offer_enroll, "an enrolled pair never offers E"); - let (pin, payload_b64, offer_node) = - offers.fido2.expect("enrolled offers FIDO2"); - assert_eq!(offer_node, node, "the open ships the ENROLLED node's short hex"); + let (pin, payload_b64, offer_node) = offers.fido2.expect("enrolled offers FIDO2"); + assert_eq!( + offer_node, node, + "the open ships the ENROLLED node's short hex" + ); assert_eq!(pin.minter, format!("sealnet:ling@{node}")); assert_eq!(pin.minted_at, 42_000, "minted_at is FIXED at the decision"); assert_eq!( @@ -15698,7 +16328,10 @@ mod tests { std::fs::write(spt_store::perch::node_key_file(), "not a hex seed").unwrap(); let offers = compose_mint_offers("ling", "sealnet", b"seal me", 42_000); assert!(offers.fido2.is_none()); - assert!(!offers.offer_enroll, "no node, no offers — plain TOTP stays whole"); + assert!( + !offers.offer_enroll, + "no node, no offers — plain TOTP stays whole" + ); }); } @@ -15748,8 +16381,14 @@ mod tests { assert_eq!(rec.ceremony_kind, "fido2"); assert_eq!(rec.signature_hex.as_deref(), Some(sig.as_str())); assert_eq!(rec.minter, minter, "the PINNED minter, stored verbatim"); - assert_eq!(rec.minted_at, 42_000, "the PINNED minted_at, stored verbatim"); - assert_eq!(rec.content_hash, spt_store::seal::content_hash_hex(b"sign me")); + assert_eq!( + rec.minted_at, 42_000, + "the PINNED minted_at, stored verbatim" + ); + assert_eq!( + rec.content_hash, + spt_store::seal::content_hash_hex(b"sign me") + ); // Self-authenticating: the record's OWN stored fields recompose // to bytes the enrolled pubkey verifies. assert_eq!( @@ -15765,7 +16404,10 @@ mod tests { ), Ok(()) ); - assert!(!ledger_path.exists(), "a proof never touches the code ledger"); + assert!( + !ledger_path.exists(), + "a proof never touches the code ledger" + ); assert!(recover(&broker.ceremonies).is_empty(), "the ceremony ended"); }); } @@ -15797,7 +16439,11 @@ mod tests { &ctrl_send, ) .unwrap(); - assert_eq!(recover(&broker.ceremonies).len(), 1, "the ceremony continues"); + assert_eq!( + recover(&broker.ceremonies).len(), + 1, + "the ceremony continues" + ); // A pinned offer whose (node x subnet) holds NO enrollment. let cid2 = insert_pending_fido2( @@ -15840,7 +16486,10 @@ mod tests { assert_eq!(recover(&broker.ceremonies).len(), 3, "still pending"); // Every refusal above: nothing spent, nothing minted. - assert!(!ledger_path.exists(), "failed proofs never touch the code ledger"); + assert!( + !ledger_path.exists(), + "failed proofs never touch the code ledger" + ); assert!(spt_store::seal::SealStore::load().records.is_empty()); // The TOTP fallback on the SAME ceremony admits — kind totp, no @@ -15853,7 +16502,10 @@ mod tests { let store = spt_store::seal::SealStore::load(); let rec = store.find(&r.token.unwrap()).unwrap(); assert_eq!(rec.ceremony_kind, "totp"); - assert!(rec.signature_hex.is_none(), "a TOTP admit records no signature"); + assert!( + rec.signature_hex.is_none(), + "a TOTP admit records no signature" + ); }); } @@ -15894,7 +16546,10 @@ mod tests { let seals = spt_store::seal::SealStore::load(); assert_eq!(seals.records.len(), 1, "exactly one seal"); let rec = seals.find(&token).unwrap(); - assert_eq!(rec.ceremony_kind, "totp", "the admitting proof was the code"); + assert_eq!( + rec.ceremony_kind, "totp", + "the admitting proof was the code" + ); assert_eq!(rec.minter, format!("sealnet:ling@{node}")); // FAILED ENROLLMENT MINTS NOTHING: the pair is now enrolled, so @@ -15908,7 +16563,11 @@ mod tests { .unwrap(); let r = seal_reply(&mut req_client); assert_eq!(r.outcome, SEAL_CEREMONY_REFUSED); - assert!(r.detail.starts_with(SEAL_ENROLL_ALREADY_ENROLLED), "{}", r.detail); + assert!( + r.detail.starts_with(SEAL_ENROLL_ALREADY_ENROLLED), + "{}", + r.detail + ); assert_eq!( spt_store::seal::SealStore::load().records.len(), 1, @@ -16029,7 +16688,10 @@ mod tests { 6, "throttled spends nothing" ); - assert!(recover(&broker.ceremonies).is_empty(), "throttled ends the wait"); + assert!( + recover(&broker.ceremonies).is_empty(), + "throttled ends the wait" + ); // ADMIT (member): the mint persists — daemon-side, fully-qualified // minter, ceremony_kind totp — and the ledger resets. @@ -16042,13 +16704,21 @@ mod tests { assert_eq!(r.outcome, SEAL_CEREMONY_ADMITTED, "{}", r.detail); let token = r.token.expect("an admit hands back the token"); let store = spt_store::seal::SealStore::load(); - let rec = store.find(&token).expect("the mint PERSISTED (daemon writer)"); - assert_eq!(rec.content_hash, spt_store::seal::content_hash_hex(b"seal me")); + let rec = store + .find(&token) + .expect("the mint PERSISTED (daemon writer)"); + assert_eq!( + rec.content_hash, + spt_store::seal::content_hash_hex(b"seal me") + ); assert_eq!(rec.ceremony_kind, "totp"); // The node half is the daemon's own node-key short hex (roster // short form), never the mutable hostname — doyle W2 gate ruling. let node = spt_net::net::registry::key_prefix( - &spt_store::nodeid::load_or_create().unwrap().public_key().to_hex(), + &spt_store::nodeid::load_or_create() + .unwrap() + .public_key() + .to_hex(), ); assert_eq!(rec.minter, format!("sealnet:ling@{node}")); assert_eq!(node.len(), 8, "roster short form: 8 hex chars"); @@ -16121,7 +16791,10 @@ mod tests { "an unpersistable bound mints nothing — the refusal fires BEFORE the mint arm" ); assert!(recover(&broker.ceremonies).is_empty(), "the ceremony ended"); - assert!(ledger_path.is_dir(), "the rig held: the path stayed a directory"); + assert!( + ledger_path.is_dir(), + "the rig held: the path stayed a directory" + ); }); } diff --git a/crates/spt-daemon/src/config.rs b/crates/spt-daemon/src/config.rs index 012060d1..4a1dd68f 100644 --- a/crates/spt-daemon/src/config.rs +++ b/crates/spt-daemon/src/config.rs @@ -645,13 +645,20 @@ mod tests { cwd: Some("/srv".to_string()), }) .unwrap(); - assert!(replaced, "a re-save of the same id replaces the prior entry"); + assert!( + replaced, + "a re-save of the same id replaces the prior entry" + ); let cfg = DaemonConfig::load(); assert_eq!(cfg.startup_endpoints.len(), 1, "replace, not append"); assert_eq!(cfg.startup_endpoints[0].adapter, "cc:gateway"); assert_eq!(cfg.startup_endpoints[0].cwd.as_deref(), Some("/srv")); - assert_eq!(cfg.pulse_period, Duration::from_millis(1234), "knob still intact"); + assert_eq!( + cfg.pulse_period, + Duration::from_millis(1234), + "knob still intact" + ); // A second distinct id → appended alongside, returns false. let replaced = DaemonConfig::upsert_startup_endpoint(StartupEndpoint { @@ -663,7 +670,11 @@ mod tests { assert!(!replaced); let cfg = DaemonConfig::load(); assert_eq!(cfg.startup_endpoints.len(), 2); - let ids: Vec<&str> = cfg.startup_endpoints.iter().map(|e| e.id.as_str()).collect(); + let ids: Vec<&str> = cfg + .startup_endpoints + .iter() + .map(|e| e.id.as_str()) + .collect(); assert!(ids.contains(&"gw") && ids.contains(&"worker")); }); } @@ -713,7 +724,11 @@ mod tests { vec!["worker"], "the sibling entry is untouched" ); - assert_eq!(cfg.pulse_period, Duration::from_millis(1234), "knob still intact"); + assert_eq!( + cfg.pulse_period, + Duration::from_millis(1234), + "knob still intact" + ); // Idempotent: a second off is a no-op that reports false. assert!(!DaemonConfig::remove_startup_endpoint("gw").unwrap()); diff --git a/crates/spt-daemon/src/conn.rs b/crates/spt-daemon/src/conn.rs index 9c51ad4e..0157b60b 100644 --- a/crates/spt-daemon/src/conn.rs +++ b/crates/spt-daemon/src/conn.rs @@ -222,7 +222,11 @@ impl Inner { // [impl->REQ-CONN-POISON-ATTRIBUTION] fn attribution(&self) -> String { let label = recover(&self.label); - let facts: &str = if label.is_empty() { "role=unattributed" } else { &label }; + let facts: &str = if label.is_empty() { + "role=unattributed" + } else { + &label + }; format!("conn={} {} {}", self.id, facts, log_stamp()) } @@ -351,10 +355,7 @@ impl Inner { if let Some(armed) = d.inflight { break armed; } - d = self - .dog_cv - .wait(d) - .unwrap_or_else(|p| p.into_inner()); + d = self.dog_cv.wait(d).unwrap_or_else(|p| p.into_inner()); }; // Sleep toward the deadline while THIS op stays in flight. let fired = loop { @@ -698,10 +699,7 @@ mod tests { let client = LocalSocketTransport::connect(&name).expect("connect"); let server = listener.accept().expect("accept"); let (_recv, send) = server.split(); - ( - BrokerConn::new(send, Duration::from_millis(2000)), - client, - ) + (BrokerConn::new(send, Duration::from_millis(2000)), client) } // [unit->REQ-CONN-POISON-DIAL-SCOPE] the F-039 leg-(a) token split: the loud @@ -722,9 +720,10 @@ mod tests { poisoned.starts_with("CONN_WRITE_POISONED:"), "deadline class keeps the loud wedge-observable token: {poisoned}" ); - let retired = conn - .inner - .render_retirement(false, Some(&io::Error::new(io::ErrorKind::BrokenPipe, "peer gone"))); + let retired = conn.inner.render_retirement( + false, + Some(&io::Error::new(io::ErrorKind::BrokenPipe, "peer gone")), + ); assert!( retired.starts_with("CONN_WRITE_RETIRED:"), "organic class emits the DISTINCT retired token: {retired}" diff --git a/crates/spt-daemon/src/crc_swap.rs b/crates/spt-daemon/src/crc_swap.rs index 6ca2aef8..bfa2a56d 100644 --- a/crates/spt-daemon/src/crc_swap.rs +++ b/crates/spt-daemon/src/crc_swap.rs @@ -367,7 +367,11 @@ mod tests { let plan = plan_crc_swap(s, i).unwrap(); let want_rel: PathBuf = ["sub", "dir", "x"].iter().collect(); - assert_eq!(rels(&plan), vec![want_rel.clone()], "nested changed file found"); + assert_eq!( + rels(&plan), + vec![want_rel.clone()], + "nested changed file found" + ); let only = &plan[0]; assert_eq!(only.staged, s.join(&want_rel)); assert_eq!(only.target, i.join(&want_rel)); @@ -392,7 +396,10 @@ mod tests { // fresh under a nested parent that does NOT yet exist in install → created. let fresh_rel: PathBuf = ["newdir", "fresh"].iter().collect(); write(&s.join(&fresh_rel), b"FRESH"); - assert!(!i.join("newdir").exists(), "precondition: nested parent absent"); + assert!( + !i.join("newdir").exists(), + "precondition: nested parent absent" + ); let plan = plan_crc_swap(s, i).unwrap(); assert_eq!( @@ -403,7 +410,11 @@ mod tests { apply_crc_swap(&plan).unwrap(); - assert_eq!(fs::read(i.join("changed")).unwrap(), b"NEW", "changed got new bytes"); + assert_eq!( + fs::read(i.join("changed")).unwrap(), + b"NEW", + "changed got new bytes" + ); assert_eq!( fs::read(i.join(&fresh_rel)).unwrap(), b"FRESH", @@ -479,7 +490,10 @@ mod tests { let result = apply_crc_swap_with(&plan, &rename); - assert!(result.is_err(), "the injected mid-loop commit failure propagates"); + assert!( + result.is_err(), + "the injected mid-loop commit failure propagates" + ); assert_eq!( fs::read(&first_target).unwrap(), b"BEFORE", @@ -647,7 +661,10 @@ mod tests { write(&s.join("bin"), b"V2"); let stranded_old = i.join("bin.old"); write(&stranded_old, b"LAST-GOOD-V1"); - assert!(!i.join("bin").exists(), "precondition: target missing (crashed pre-commit)"); + assert!( + !i.join("bin").exists(), + "precondition: target missing (crashed pre-commit)" + ); let plan = plan_crc_swap(s, i).unwrap(); apply_crc_swap(&plan).unwrap(); @@ -692,9 +709,19 @@ mod tests { let plan = plan_crc_swap(s, i).unwrap(); let err = apply_crc_swap_with(&plan, &rename).expect_err("the injected displace fails"); let msg = err.to_string(); - assert!(msg.contains("crc_swap displace original"), "names the op: {msg}"); + assert!( + msg.contains("crc_swap displace original"), + "names the op: {msg}" + ); assert!(msg.contains("bin"), "carries the paths: {msg}"); - assert!(msg.contains("bin.old"), "carries the displacement target: {msg}"); - assert_eq!(err.kind(), std::io::ErrorKind::PermissionDenied, "preserves kind"); + assert!( + msg.contains("bin.old"), + "carries the displacement target: {msg}" + ); + assert_eq!( + err.kind(), + std::io::ErrorKind::PermissionDenied, + "preserves kind" + ); } } diff --git a/crates/spt-daemon/src/daemon.rs b/crates/spt-daemon/src/daemon.rs index 23a0dc9a..2b94393a 100644 --- a/crates/spt-daemon/src/daemon.rs +++ b/crates/spt-daemon/src/daemon.rs @@ -74,7 +74,9 @@ impl Daemon { #[cfg(unix)] if let Some(invoker) = crate::deelevate::daemon_target_user() { match invoker.drop_in_process() { - Ok(()) => spt_proto::emit_line_err!("DEELEVATED: daemon dropped to uid {}", invoker.uid), + Ok(()) => { + spt_proto::emit_line_err!("DEELEVATED: daemon dropped to uid {}", invoker.uid) + } // A drop target existed but the drop failed: serving as // root would root the user's state universe — a known-torn // state. ABORT (user-ratified 2026-06-06: refuse, don't limp). @@ -94,7 +96,11 @@ impl Daemon { // --detached BELT (REQ-HAZARD-DETACHED-DAEMON-STDIO): the respawned // unelevated daemon then runs detach_console + the null-handles guard, // so it never keeps live inherited stdio (matches every other rung). - &["daemon".to_string(), "run".to_string(), "--detached".to_string()], + &[ + "daemon".to_string(), + "run".to_string(), + "--detached".to_string(), + ], ) { Ok(Some(pid)) => { spt_proto::emit_line_err!( @@ -146,7 +152,9 @@ impl Daemon { &DaemonConfig::load().detached_subnets, ); if let Err(e) = att.save() { - spt_proto::emit_line_err!("ATTACHMENT_RESET_FAIL: {e} — serving with all subnets attached"); + spt_proto::emit_line_err!( + "ATTACHMENT_RESET_FAIL: {e} — serving with all subnets attached" + ); } for name in &att.detached { // Plain prose (no Markdown markers): spt-daemon can't import the @@ -154,7 +162,9 @@ impl Daemon { // marker-free rather than rendered. The `SUBNET_DETACHED:{name}` // token is the machine contract; the rest is a human hint. // [impl->REQ-CLI-OUTPUT-MARKDOWN] - spt_proto::emit_line_err!("SUBNET_DETACHED:{name} (startup default — run: spt subnet attach {name})"); + spt_proto::emit_line_err!( + "SUBNET_DETACHED:{name} (startup default — run: spt subnet attach {name})" + ); } } @@ -173,7 +183,9 @@ impl Daemon { let owlery = spt_store::perch::owlery_dir(); let report = perchgc::sweep(&owlery, false); if !report.root_readable { - spt_proto::emit_line_err!("PERCH_CENSUS_SKIPPED: perch tree unreadable — nothing classified"); + spt_proto::emit_line_err!( + "PERCH_CENSUS_SKIPPED: perch tree unreadable — nothing classified" + ); return; } spt_proto::emit_line_err!( @@ -205,7 +217,9 @@ impl Daemon { let net = if node_hex.is_some() { try_start_net() } else { - spt_proto::emit_line_err!("NODE_KEY_FAIL: identity unavailable — broker runs net-less, no retry"); + spt_proto::emit_line_err!( + "NODE_KEY_FAIL: identity unavailable — broker runs net-less, no retry" + ); None }; @@ -223,13 +237,13 @@ impl Daemon { thread::spawn(move || { let _ = serve_broker.serve(); }); - // Inbound net dispatch + outbound peer pump (D9-1) now run in - // the BRAIN child (restoration D2-1): they are pure IPC clients, - // so they live with the restartable brain and respawn with it. - // The broker keeps only the NetHost bring-up and the boot-race - // self-heal that binds it; the brain polls `net-status` and - // starts the consumers once net reports enabled. - // [impl->REQ-HAZARD-BROKER-PROCESS-ISOLATION] + // Inbound net dispatch + outbound peer pump (D9-1) now run in + // the BRAIN child (restoration D2-1): they are pure IPC clients, + // so they live with the restartable brain and respawn with it. + // The broker keeps only the NetHost bring-up and the boot-race + // self-heal that binds it; the brain polls `net-status` and + // starts the consumers once net reports enabled. + // [impl->REQ-HAZARD-BROKER-PROCESS-ISOLATION] if !net_up && node_hex.is_some() { // Boot-race self-heal (REQ-DAEMON-9): net failed to bind // but identity is sound — almost always the autostart @@ -253,9 +267,7 @@ impl Daemon { // is watching, which degrades a signal rather than a surface. // [impl->REQ-ATTACH-LINK-PUSH] // [impl->REQ-ATTACH-AWAY-ALERTS] - if let Err(e) = - crate::attachment::spawn_attach_observer(Arc::clone(&broker)) - { + if let Err(e) = crate::attachment::spawn_attach_observer(Arc::clone(&broker)) { spt_proto::emit_line_err!( "ATTACH_OBSERVER_UNSPAWNED: {e} — linked shells will not \ receive attachment frames this daemon lifetime" @@ -278,11 +290,11 @@ impl Daemon { { let port = crate::docshost::resolve_daemon_docs_port( crate::config::DaemonConfig::load().docs_port, - std::env::var(crate::docshost::DOCS_PORT_ENV).ok().as_deref(), - std::env::var_os( - crate::docshost::TEST_EPHEMERAL_ADVISORY_PORTS_ENV, - ) - .is_some_and(|value| value == "1"), + std::env::var(crate::docshost::DOCS_PORT_ENV) + .ok() + .as_deref(), + std::env::var_os(crate::docshost::TEST_EPHEMERAL_ADVISORY_PORTS_ENV) + .is_some_and(|value| value == "1"), ); let docs_root = spt_store::perch::spt_home().join("docs"); match crate::docshost::start(docs_root, port) { @@ -547,12 +559,17 @@ fn net_retry_attach(broker: Arc) { thread::sleep(backoff); if let Some(host) = try_start_net() { if broker.attach_net(host) { - spt_proto::emit_line_err!("NET_ATTACHED: net endpoint bound on retry — brain starts the consumers"); + spt_proto::emit_line_err!( + "NET_ATTACHED: net endpoint bound on retry — brain starts the consumers" + ); } return; } backoff = net_retry_backoff(backoff); - spt_proto::emit_line_err!("NET_BIND_RETRY: net still unavailable, retrying in {}s", backoff.as_secs()); + spt_proto::emit_line_err!( + "NET_BIND_RETRY: net still unavailable, retrying in {}s", + backoff.as_secs() + ); } } @@ -660,7 +677,10 @@ pub fn ensure_running_outcome() -> io::Result { match ensure_decision(is_running(), spt_store::daemon_inhibit::stop_inhibited()) { EnsureOutcome::AlreadyRunning => return Ok(EnsureOutcome::AlreadyRunning), EnsureOutcome::DeclinedStopInhibited => { - spt_proto::emit_line_err!("DAEMON_START_DECLINED: {}", spt_store::daemon_inhibit::REFUSAL_LINE); + spt_proto::emit_line_err!( + "DAEMON_START_DECLINED: {}", + spt_store::daemon_inhibit::REFUSAL_LINE + ); return Ok(EnsureOutcome::DeclinedStopInhibited); } EnsureOutcome::Started => {} @@ -680,7 +700,10 @@ pub fn ensure_running_outcome() -> io::Result { match ensure_decision(is_running(), spt_store::daemon_inhibit::stop_inhibited()) { EnsureOutcome::AlreadyRunning => return Ok(EnsureOutcome::AlreadyRunning), EnsureOutcome::DeclinedStopInhibited => { - spt_proto::emit_line_err!("DAEMON_START_DECLINED: {}", spt_store::daemon_inhibit::REFUSAL_LINE); + spt_proto::emit_line_err!( + "DAEMON_START_DECLINED: {}", + spt_store::daemon_inhibit::REFUSAL_LINE + ); return Ok(EnsureOutcome::DeclinedStopInhibited); } EnsureOutcome::Started => {} @@ -689,7 +712,9 @@ pub fn ensure_running_outcome() -> io::Result { // implicit anchors exactly ONE line appears — the countable observable that // the serialization holds, and the field diagnostic for a convoy if it ever // returns. - spt_proto::emit_line_err!("DAEMON_AUTOSTART: no daemon and no standing operator stop — starting one"); + spt_proto::emit_line_err!( + "DAEMON_AUTOSTART: no daemon and no standing operator stop — starting one" + ); spawn_and_wait()?; Ok(EnsureOutcome::Started) } @@ -705,7 +730,9 @@ fn spawn_and_wait() -> io::Result<()> { // daemon rather than leave the caller daemon-less. The autostart // path must never hard-fail when a spawn would have worked. if let Err(e) = svc.start() { - spt_proto::emit_line_err!("DAEMON_SERVICE_START_FALLBACK: {e} — starting a manual daemon"); + spt_proto::emit_line_err!( + "DAEMON_SERVICE_START_FALLBACK: {e} — starting a manual daemon" + ); spawn_detached()?; } } @@ -763,7 +790,9 @@ pub fn start_daemon() -> io::Result { // Manager present but undrivable (no session bus) — fall back to a // manual daemon so `daemon start` still brings one up. Err(e) => { - spt_proto::emit_line_err!("DAEMON_SERVICE_START_FALLBACK: {e} — starting a manual daemon"); + spt_proto::emit_line_err!( + "DAEMON_SERVICE_START_FALLBACK: {e} — starting a manual daemon" + ); spawn_detached()?; wait_until_up()?; Ok(StartOutcome::Spawned) @@ -1189,7 +1218,10 @@ pub(crate) fn create_process_detached_keep_handle( let mut block = (!env.is_empty() || !env_remove.is_empty()).then(|| unicode_env_block(env, env_remove)); let (env_ptr, env_flag) = match block.as_mut() { - Some(b) => (b.as_mut_ptr() as *mut core::ffi::c_void, CREATE_UNICODE_ENVIRONMENT), + Some(b) => ( + b.as_mut_ptr() as *mut core::ffi::c_void, + CREATE_UNICODE_ENVIRONMENT, + ), None => (std::ptr::null_mut(), 0), }; let mut si_ex: StartupInfoExW = unsafe { std::mem::zeroed() }; @@ -1616,7 +1648,11 @@ impl DetachedChild { if err.raw_os_error() == Some(libc::ESRCH) { None } else { - Some(tree_kill_incomplete_line(self.pid, "its process group", &err)) + Some(tree_kill_incomplete_line( + self.pid, + "its process group", + &err, + )) } } else { None @@ -2184,7 +2220,10 @@ fn spawn_daemon_via_wmi(program: &str, args: &[String]) -> io::Result { let ps_literal = wmi_cmdline.replace('\'', "''"); let script = wmi_create_script(&ps_literal); // -EncodedCommand wants base64 of the UTF-16LE script bytes. - let utf16le: Vec = script.encode_utf16().flat_map(|u| u.to_le_bytes()).collect(); + let utf16le: Vec = script + .encode_utf16() + .flat_map(|u| u.to_le_bytes()) + .collect(); let encoded = B64.encode(&utf16le); const POWERSHELL_ABS: &str = r"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"; @@ -2341,14 +2380,16 @@ mod tests { }; let env = vec![("SPT_ENV_PROBE".to_string(), "7".to_string())]; - let mut child = detached_no_inherit_env(program, &probe, &env, &[], None).expect("spawn probe"); + let mut child = + detached_no_inherit_env(program, &probe, &env, &[], None).expect("spawn probe"); assert_eq!( child.wait_ms(30_000).expect("wait"), Some(7), "the addition never reached the child" ); - let mut child = detached_no_inherit_env(program, &inherited, &env, &[], None).expect("spawn probe"); + let mut child = + detached_no_inherit_env(program, &inherited, &env, &[], None).expect("spawn probe"); assert_eq!( child.wait_ms(30_000).expect("wait"), Some(5), @@ -2380,7 +2421,10 @@ mod tests { } else { ( "sh", - vec!["-c".into(), format!("[ -n \"${PROBE}\" ] && exit 5; exit 0")], + vec![ + "-c".into(), + format!("[ -n \"${PROBE}\" ] && exit 5; exit 0"), + ], ) }; std::env::set_var(PROBE, "leaked"); @@ -2442,8 +2486,9 @@ mod tests { let (program, args): (&str, Vec) = ("cmd", vec!["/c".into(), "ping -n 30 127.0.0.1".into()]); - let mut child = detached_no_inherit_env_windowless(program, &args, &[], &[], Some(&capture)) - .expect("spawn with capture"); + let mut child = + detached_no_inherit_env_windowless(program, &args, &[], &[], Some(&capture)) + .expect("spawn with capture"); // The parent lets go. Anything still holding the canary now is the child. drop(canary); @@ -2542,10 +2587,9 @@ mod tests { let job = match self.in_our_job { Some(true) => "field 1: IN OUR JOB at selection".to_string(), Some(false) => "field 1: NOT in our job at selection".to_string(), - None => - "field 1: UNASKABLE here (no job at spawn, the candidate was already \ + None => "field 1: UNASKABLE here (no job at spawn, the candidate was already \ gone, or this platform has no Job Objects) — no verdict from it" - .to_string(), + .to_string(), }; let birth = match (self.candidate_born, self.parent_born) { (Some(c), Some(p)) if c < p => format!( @@ -2667,7 +2711,8 @@ mod tests { ("sh", vec!["-c".into(), "sleep 120 & wait".into()]) }; - let mut child = detached_no_inherit_env_windowless(program, &args, &[], &[], None).expect("spawn the parent"); + let mut child = detached_no_inherit_env_windowless(program, &args, &[], &[], None) + .expect("spawn the parent"); // Find the grandchild by PARENTAGE rather than by anything it reports: // the process table is the same oracle the orphan sweep uses, and a // grandchild that has to cooperate to be found is a rig that cannot @@ -2737,9 +2782,8 @@ mod tests { census.push(format!( "pid {pid} REJECTED ({}; {})", match (born, parent_born) { - (Some(c), Some(p)) if c < p => format!( - "born {c} BEFORE the parent's {p} — cannot be its descendant" - ), + (Some(c), Some(p)) if c < p => + format!("born {c} BEFORE the parent's {p} — cannot be its descendant"), (Some(_), Some(_)) => "born after the parent — age is fine".to_string(), _ => "no birth stamp on one side — undiscriminable".to_string(), }, @@ -2910,7 +2954,8 @@ mod tests { let (program, args): (&str, Vec) = ("cmd", vec!["/c".into(), "ping -n 30 127.0.0.1".into()]); - let mut child = detached_no_inherit_env_windowless(program, &args, &[], &[], None).expect("spawn"); + let mut child = + detached_no_inherit_env_windowless(program, &args, &[], &[], None).expect("spawn"); assert_ne!( child.job, 0, "the rig needs a REAL job to poison — a spawn that never got one proves nothing here" @@ -2957,7 +3002,8 @@ mod tests { } else { ("sleep", vec!["30".into()]) }; - let mut child = detached_no_inherit_env_windowless(program, &args, &[], &[], None).expect("spawn"); + let mut child = + detached_no_inherit_env_windowless(program, &args, &[], &[], None).expect("spawn"); assert!( child.kill_tree_reporting().is_none(), @@ -2980,8 +3026,8 @@ mod tests { fn an_already_reaped_group_is_quiet() { use std::time::Instant; - let mut child = detached_no_inherit_env("sleep", &["30".into()], &[], &[], None) - .expect("spawn"); + let mut child = + detached_no_inherit_env("sleep", &["30".into()], &[], &[], None).expect("spawn"); assert!( child.kill_tree_reporting().is_none(), "the live teardown must be silent" @@ -3090,7 +3136,10 @@ mod tests { const FILE_TYPE_UNKNOWN: u32 = 0x0000; const FILE_TYPE_DISK: u32 = 0x0001; const FILE_TYPE_CHAR: u32 = 0x0002; - assert!(should_null_std_handles(FILE_TYPE_PIPE), "an undrained pipe blocks ⇒ null"); + assert!( + should_null_std_handles(FILE_TYPE_PIPE), + "an undrained pipe blocks ⇒ null" + ); assert!( !should_null_std_handles(FILE_TYPE_DISK), "a FILE redirect (2>run.log / the int-test brain-log) is disk ⇒ survives" @@ -3111,9 +3160,19 @@ mod tests { #[test] fn net_retry_backoff_doubles_then_caps() { assert_eq!(net_retry_backoff(NET_RETRY_FIRST), Duration::from_secs(2)); - assert_eq!(net_retry_backoff(Duration::from_secs(2)), Duration::from_secs(4)); - assert_eq!(net_retry_backoff(Duration::from_secs(16)), Duration::from_secs(30)); - assert_eq!(net_retry_backoff(NET_RETRY_CAP), NET_RETRY_CAP, "stays capped"); + assert_eq!( + net_retry_backoff(Duration::from_secs(2)), + Duration::from_secs(4) + ); + assert_eq!( + net_retry_backoff(Duration::from_secs(16)), + Duration::from_secs(30) + ); + assert_eq!( + net_retry_backoff(NET_RETRY_CAP), + NET_RETRY_CAP, + "stays capped" + ); } // [unit->REQ-HAZARD-DETACHED-PIPE-INHERIT] the no-inherit spawn's command @@ -3160,7 +3219,10 @@ mod tests { #[test] fn wmi_create_script_carries_the_no_window_startup_spec() { let s = wmi_create_script("cmd.exe /c rem"); - assert!(s.contains("Win32_ProcessStartup"), "a startup spec is built"); + assert!( + s.contains("Win32_ProcessStartup"), + "a startup spec is built" + ); assert!( s.contains("ProcessStartupInformation=$si"), "the startup spec is passed to Win32_Process.Create" @@ -3236,7 +3298,10 @@ mod tests { Err(io::Error::other(format!("{rung:?} failed"))) }); let e = r.expect_err("all rungs failed → Err"); - assert!(e.to_string().contains("InJob"), "the LAST rung's error: {e}"); + assert!( + e.to_string().contains("InJob"), + "the LAST rung's error: {e}" + ); assert_eq!( seen, vec![ @@ -3319,11 +3384,8 @@ mod tests { fn GetCurrentProcess() -> isize; fn IsProcessInJob(proc_h: isize, job_h: isize, result: *mut i32) -> i32; } - let gc = detached_no_inherit( - "ping", - &["-n".into(), "300".into(), "127.0.0.1".into()], - ) - .expect("launcher: breakaway spawn of grandchild"); + let gc = detached_no_inherit("ping", &["-n".into(), "300".into(), "127.0.0.1".into()]) + .expect("launcher: breakaway spawn of grandchild"); // Diag: is the launcher itself in a job? is the broken-away gc in ANY // job? (job_h = 0 → "any job"). Written before pidfile so the parent // sees it on read. @@ -3356,8 +3418,7 @@ mod tests { // KILL_ON_JOB_CLOSE so terminating the job reaps everything still in it; // BREAKAWAY_OK so a child created WITH CREATE_BREAKAWAY_FROM_JOB may escape // (the permissive shape; a job WITHOUT it would fail the spawn → fall back). - info.basic.limit_flags = - JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK; + info.basic.limit_flags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK; let ok = unsafe { SetInformationJobObject( job, @@ -3371,9 +3432,15 @@ mod tests { let launcher = Command::new(std::env::current_exe().unwrap()) // a unique substring filter selects ONLY this test in the re-run; the // env presence routes it to the launcher arm above (no recursion). - .args(["breakaway_spawn_escapes_a_kill_on_close_job", "--test-threads=1"]) + .args([ + "breakaway_spawn_escapes_a_kill_on_close_job", + "--test-threads=1", + ]) .env("SPT_BREAKAWAY_PIDFILE", &pidfile) - .env("SPT_BREAKAWAY_DIAG", std::env::temp_dir().join(format!("spt_breakaway_diag_{}.log", std::process::id()))) + .env( + "SPT_BREAKAWAY_DIAG", + std::env::temp_dir().join(format!("spt_breakaway_diag_{}.log", std::process::id())), + ) // CREATE_BREAKAWAY_FROM_JOB: escape the test-runner's OWN ancestor job // (cargo/CI run the test harness inside a job), so MY job below becomes // the launcher's ONLY job — otherwise the grandchild's breakaway lands @@ -3405,8 +3472,7 @@ mod tests { }; // Assign the launcher to the job BEFORE it spawns its grandchild — the // grandchild is created with breakaway, so it leaves the job at birth. - let assigned = - unsafe { AssignProcessToJobObject(job, launcher.as_raw_handle() as isize) }; + let assigned = unsafe { AssignProcessToJobObject(job, launcher.as_raw_handle() as isize) }; assert!(assigned != 0, "assign launcher to job"); // Read back the grandchild pid. @@ -3448,7 +3514,8 @@ mod tests { let _ = launcher.wait(); unsafe { CloseHandle(job) }; let _ = std::fs::remove_file(&pidfile); - let diagpath = std::env::temp_dir().join(format!("spt_breakaway_diag_{}.log", std::process::id())); + let diagpath = + std::env::temp_dir().join(format!("spt_breakaway_diag_{}.log", std::process::id())); let diag = std::fs::read_to_string(&diagpath).unwrap_or_default(); let _ = std::fs::remove_file(&diagpath); diff --git a/crates/spt-daemon/src/deadline.rs b/crates/spt-daemon/src/deadline.rs index 23bddf27..049a4189 100644 --- a/crates/spt-daemon/src/deadline.rs +++ b/crates/spt-daemon/src/deadline.rs @@ -348,7 +348,10 @@ mod tests { DeadlineAnchor::open("agent-b", 100, StartReason::Crash, 5_000).unwrap(); // Re-open A in update mode → its own anchor survived B's write. let a = DeadlineAnchor::open("agent-a", 100, StartReason::Update, 9_999).unwrap(); - assert_eq!(a.anchor_ms, 1_000, "agent-a's phase must survive agent-b's write"); + assert_eq!( + a.anchor_ms, 1_000, + "agent-a's phase must survive agent-b's write" + ); assert_ne!(anchor_path("agent-a"), anchor_path("agent-b")); }); } diff --git a/crates/spt-daemon/src/deelevate.rs b/crates/spt-daemon/src/deelevate.rs index 9210cfb2..db831d26 100644 --- a/crates/spt-daemon/src/deelevate.rs +++ b/crates/spt-daemon/src/deelevate.rs @@ -297,7 +297,9 @@ mod unix { Some(target) } None => { - spt_proto::emit_line_err!("ELECTION_UNKNOWN_USER:{chosen} — using {default_name} unelected"); + spt_proto::emit_line_err!( + "ELECTION_UNKNOWN_USER:{chosen} — using {default_name} unelected" + ); Some(invoker) } } @@ -783,7 +785,11 @@ mod windows { (ok, io::Error::last_os_error()) }; let (mut ok, mut err) = call(FLAGS | CREATE_BREAKAWAY_FROM_JOB); - if ok == 0 && matches!(err.raw_os_error(), Some(ERROR_INVALID_PARAMETER) | Some(ERROR_ACCESS_DENIED)) + if ok == 0 + && matches!( + err.raw_os_error(), + Some(ERROR_INVALID_PARAMETER) | Some(ERROR_ACCESS_DENIED) + ) { spt_proto::emit_line_err!( "DEELEVATE_BREAKAWAY_DENIED: token spawn rejected CREATE_BREAKAWAY_FROM_JOB \ @@ -861,10 +867,7 @@ mod tests { fn env_overlay_keeps_explicit_spt_home_alive() { // Replace: desktop block already has SPT_HOME (the default home). let b = block(&["PATH=C:\\win", "spt_home=C:\\default"]); - let out = apply_env_overrides( - &b, - &[("SPT_HOME".to_string(), "C:\\accept".to_string())], - ); + let out = apply_env_overrides(&b, &[("SPT_HOME".to_string(), "C:\\accept".to_string())]); let got = parse(&out); assert!(got.contains(&"PATH=C:\\win".to_string())); assert!(got.contains(&"SPT_HOME=C:\\accept".to_string())); @@ -880,10 +883,7 @@ mod tests { // Append: block has no SPT_HOME. let b = block(&["PATH=C:\\win"]); - let out = apply_env_overrides( - &b, - &[("SPT_HOME".to_string(), "C:\\accept".to_string())], - ); + let out = apply_env_overrides(&b, &[("SPT_HOME".to_string(), "C:\\accept".to_string())]); assert!(parse(&out).contains(&"SPT_HOME=C:\\accept".to_string())); // No overrides: block passes through unchanged. diff --git a/crates/spt-daemon/src/digest.rs b/crates/spt-daemon/src/digest.rs index d2a32ece..e9c7aa08 100644 --- a/crates/spt-daemon/src/digest.rs +++ b/crates/spt-daemon/src/digest.rs @@ -73,7 +73,10 @@ pub struct DigestOverride { /// `[digest]` declared defaults, then the consumer override on top (ADR-0019 /// presentation precedence). // [impl->REQ-TERM-5] -pub fn resolve_config(adapter_digest: Option<&ManifestDigest>, over: &DigestOverride) -> DigestConfig { +pub fn resolve_config( + adapter_digest: Option<&ManifestDigest>, + over: &DigestOverride, +) -> DigestConfig { let mut cfg = DigestConfig::default(); if let Some(d) = adapter_digest { if let Some(w) = d.window_turns { @@ -282,7 +285,8 @@ fn activity_spanned( // partitioned transcript (e.g. CC munges cwd into its project slug); spt-core // never munges it into a harness-specific key. if let Some(c) = cwd { - keys.entry("cwd".to_string()).or_insert_with(|| c.to_string()); + keys.entry("cwd".to_string()) + .or_insert_with(|| c.to_string()); } // [impl->REQ-INSTALL-11] the extractor binary resolves from the adapter // install dir (record `source_dir`) before PATH. @@ -317,7 +321,8 @@ fn activity_spanned( if let Some((sid, f)) = &first_drop { spt_proto::emit_line_err!( "DIGEST_SKIP:{id} dropped={total_drops} first_session={sid} first_line={} reason={}", - f.line_no, f.reason + f.line_no, + f.reason ); } items @@ -457,7 +462,8 @@ fn log_less_activity(id: &str, perch_path: &std::path::Path) -> Vec = merged @@ -656,7 +673,11 @@ mod tests { TimelineItem::Boundary { kind, .. } => kind.as_str(), }) .collect(); - assert_eq!(order, vec!["first", "msg", "third"], "context slots in by ts"); + assert_eq!( + order, + vec!["first", "msg", "third"], + "context slots in by ts" + ); } // Supersede test helpers: an Activity at a given generation (ordinal) + localseq, @@ -673,7 +694,10 @@ mod tests { } } fn sup_bound() -> TimelineItem { - TimelineItem::Boundary { kind: "clear".into(), ts: None } + TimelineItem::Boundary { + kind: "clear".into(), + ts: None, + } } fn texts(items: &[TimelineItem]) -> Vec<&str> { items @@ -709,10 +733,15 @@ mod tests { TimelineItem::Activity { record, seq } if record.text == "shared row" => Some(*seq), _ => None, }); - assert_eq!(seq.map(|s| s >> 32), Some(1), "survivor is B's (newest) ordinal"); + assert_eq!( + seq.map(|s| s >> 32), + Some(1), + "survivor is B's (newest) ordinal" + ); // A's row + the /clear boundary emptied ancestor → no orphaned divider. assert!( - !out.iter().any(|it| matches!(it, TimelineItem::Boundary { .. })), + !out.iter() + .any(|it| matches!(it, TimelineItem::Boundary { .. })), "the divider adjacent to the fully-superseded ancestor is trimmed: {out:?}" ); } @@ -727,7 +756,11 @@ mod tests { sup_act("dup", "2026-06-13T21:00:00Z", 3, 1), // same gen, real repeat ]; let out = supersede_cross_generation(items); - assert_eq!(texts(&out), vec!["dup", "dup"], "same-ordinal repeats both survive"); + assert_eq!( + texts(&out), + vec!["dup", "dup"], + "same-ordinal repeats both survive" + ); } // [unit->REQ-DIGEST-GENERATION-SUPERSEDE] disjoint sessions (a genuine /clear, @@ -741,9 +774,15 @@ mod tests { sup_act("after clear", "2026-06-13T21:00:10Z", 1, 0), ]; let out = supersede_cross_generation(items); - assert_eq!(texts(&out), vec!["before clear", "after clear"], "both rows retained"); assert_eq!( - out.iter().filter(|it| matches!(it, TimelineItem::Boundary { .. })).count(), + texts(&out), + vec!["before clear", "after clear"], + "both rows retained" + ); + assert_eq!( + out.iter() + .filter(|it| matches!(it, TimelineItem::Boundary { .. })) + .count(), 1, "the /clear divider between two ≥1-row sessions is preserved" ); @@ -763,9 +802,15 @@ mod tests { sup_act("C tail", "2026-06-13T21:00:09Z", 2, 1), ]; let out = supersede_cross_generation(items); - assert_eq!(texts(&out), vec!["A only", "replayed", "C tail"], "B emptied, one 'replayed' under C"); assert_eq!( - out.iter().filter(|it| matches!(it, TimelineItem::Boundary { .. })).count(), + texts(&out), + vec!["A only", "replayed", "C tail"], + "B emptied, one 'replayed' under C" + ); + assert_eq!( + out.iter() + .filter(|it| matches!(it, TimelineItem::Boundary { .. })) + .count(), 1, "exactly one divider between the two surviving sessions (A | C)" ); diff --git a/crates/spt-daemon/src/dispatch.rs b/crates/spt-daemon/src/dispatch.rs index 0f9e0a77..7e4cb1ab 100644 --- a/crates/spt-daemon/src/dispatch.rs +++ b/crates/spt-daemon/src/dispatch.rs @@ -68,22 +68,22 @@ use spt_net::net::presencemsg::Presence; use spt_net::net::replicate::{ FeedDecoder as RegistryDecoder, NodeLabelUpdate, RegistryFeedRecord, RegistryUpdate, }; -use spt_net::net::wanmsg::{WanDecoder, WanReply}; use spt_net::net::sealmsg::SealFeedDecoder; +use spt_net::net::wanmsg::{WanDecoder, WanReply}; use spt_store::contextstore::ContextStore; -use spt_store::notif::NotifStore; use spt_store::enroll::{EnrollMergeOutcome, EnrollStore}; -use spt_store::seal::{SealMergeOutcome, SealStore}; +use spt_store::notif::NotifStore; use spt_store::perch; use spt_store::roster::RosterStore; +use spt_store::seal::{SealMergeOutcome, SealStore}; use crate::attach::serve_attach; use crate::brain::{Brain, BrokerEvent}; use crate::notifsync::{apply_notif_feed, NotifPolicy}; -use crate::sealsync::{apply_seal_feed, SealApplyVerdict}; use crate::propagate::serve_update; use crate::registryhost::{RegistryGatePolicy, RegistryHost}; use crate::relcache::ReleaseCache; +use crate::sealsync::{apply_seal_feed, SealApplyVerdict}; use crate::sync::{serve_sync, SyncPolicy}; use crate::wan::receive_wan; use crate::xfer::serve_xfer; @@ -2154,12 +2154,7 @@ fn serve_wan_feed( let reply = WanReply { outcome: outcome.token().to_string(), }; - let _ = brain.net_stream_send( - stream_id, - &reply.encode_line(), - None, - true, - ); + let _ = brain.net_stream_send(stream_id, &reply.encode_line(), None, true); replied = true; } } @@ -2467,7 +2462,8 @@ mod tests { // hung off it classifies as an ordinary KNOCK on this very version — so // an N-1 minter would have queued it in somebody's inbox and answered a // knock-shaped ack to a redemption. Misread, not dropped. - let knock = spt_net::net::knockmsg::KnockRecord::new("k-1", "doyle", "ling", vec![], false, false); + let knock = + spt_net::net::knockmsg::KnockRecord::new("k-1", "doyle", "ling", vec![], false, false); let kline = knock.encode_line(); let mut as_field: serde_json::Value = serde_json::from_slice(&kline[..kline.len() - 1]).unwrap(); @@ -2782,19 +2778,34 @@ mod tests { // Fresh row → claimable with zero prior failures. assert_eq!(should_claim(None, now), Some(0)); // In flight / terminal → never. - assert_eq!(should_claim(Some(&ClaimState::InFlight { attempts: 0 }), now), None); + assert_eq!( + should_claim(Some(&ClaimState::InFlight { attempts: 0 }), now), + None + ); assert_eq!(should_claim(Some(&ClaimState::Terminal), now), None); // Failure #1 releases with backoff — NOT claimable before next_at, // claimable at/after it, carrying the attempt count. let failed = DispatchOutcome::Failed("io".into()); let (s1, _) = outcome_transition(&failed, None, 0, now, Duration::ZERO); - let ClaimState::Retry { attempts: 1, next_at } = s1 else { + let ClaimState::Retry { + attempts: 1, + next_at, + } = s1 + else { panic!("failure #1 must requeue, got {s1:?}"); }; assert_eq!(next_at, now + retry_backoff(1)); - assert_eq!(should_claim(Some(&s1), now), None, "backoff holds the claim"); - assert_eq!(should_claim(Some(&s1), next_at), Some(1), "due → reclaimable"); + assert_eq!( + should_claim(Some(&s1), now), + None, + "backoff holds the claim" + ); + assert_eq!( + should_claim(Some(&s1), next_at), + Some(1), + "due → reclaimable" + ); // Backoff doubles per attempt. assert_eq!(retry_backoff(2), retry_backoff(1) * 2); @@ -2804,13 +2815,32 @@ mod tests { let (s2, _) = outcome_transition(&failed, None, 1, now, Duration::ZERO); assert!(matches!(s2, ClaimState::Retry { attempts: 2, .. })); let (s3, retire3) = outcome_transition(&failed, None, 2, now, Duration::ZERO); - assert_eq!(s3, ClaimState::Terminal, "attempt {MAX_DISPATCH_ATTEMPTS} exhausts the budget"); - assert!(!retire3, "a request/reply budget exhaustion never terminal-retires the row"); + assert_eq!( + s3, + ClaimState::Terminal, + "attempt {MAX_DISPATCH_ATTEMPTS} exhausts the budget" + ); + assert!( + !retire3, + "a request/reply budget exhaustion never terminal-retires the row" + ); // Terminal CLASSIFICATION outcomes are terminal immediately — a // served exchange and an unclassifiable stream never retry. - assert_eq!(outcome_transition(&DispatchOutcome::Served("ok".into()), None, 0, now, Duration::ZERO), (ClaimState::Terminal, false)); - assert_eq!(outcome_transition(&DispatchOutcome::Unknown, None, 0, now, Duration::ZERO), (ClaimState::Terminal, false)); + assert_eq!( + outcome_transition( + &DispatchOutcome::Served("ok".into()), + None, + 0, + now, + Duration::ZERO + ), + (ClaimState::Terminal, false) + ); + assert_eq!( + outcome_transition(&DispatchOutcome::Unknown, None, 0, now, Duration::ZERO), + (ClaimState::Terminal, false) + ); } // [unit->REQ-DISPATCH-FALLBACK-CIRCUIT] the failure classification table: @@ -2887,7 +2917,10 @@ mod tests { assert_eq!(b.trip(now), BREAKER_BASE); assert!(b.open(now)); assert!(b.open(now + BREAKER_BASE - Duration::from_millis(1))); - assert!(!b.open(now + BREAKER_BASE), "window elapses -> claiming resumes"); + assert!( + !b.open(now + BREAKER_BASE), + "window elapses -> claiming resumes" + ); // Consecutive trips double... (2s, 4s, 8s, 16s, 32s->30s cap) assert_eq!(b.trip(now), BREAKER_BASE * 2); @@ -2914,8 +2947,9 @@ mod tests { fn seat_blocked_requeues_budget_free_paced_by_the_breaker_window() { let now = Instant::now(); let window = Duration::from_secs(4); - let blocked = - DispatchOutcome::Failed("stream 9 subscriber busy: prior subscriber still draining".into()); + let blocked = DispatchOutcome::Failed( + "stream 9 subscriber busy: prior subscriber still draining".into(), + ); // Even AT the terminal edge (attempts = MAX-1), SeatBlocked keeps the // attempt count and paces on the breaker window instead of Terminal. @@ -2956,8 +2990,9 @@ mod tests { fn oneway_seatblocked_strikes_out_terminal_while_request_reply_paces_forever() { let now = Instant::now(); let window = Duration::from_secs(4); - let blocked = - DispatchOutcome::Failed("stream 9 subscriber busy: prior subscriber still draining".into()); + let blocked = DispatchOutcome::Failed( + "stream 9 subscriber busy: prior subscriber still draining".into(), + ); let registry = Some(StreamFamily::Registry); // Strikes 1..budget-1 requeue on the breaker window, counting. @@ -2976,7 +3011,11 @@ mod tests { // At the budget: TERMINAL + physical terminal-retire, loudly. let (s_out, r_out) = outcome_transition(&blocked, registry, ONEWAY_POISON_STRIKES - 1, now, window); - assert_eq!(s_out, ClaimState::Terminal, "budget spent -> terminal claim"); + assert_eq!( + s_out, + ClaimState::Terminal, + "budget spent -> terminal claim" + ); assert!(r_out, "budget spent -> the row itself retires terminal"); // The identical failure at the identical count on a request/reply @@ -3000,7 +3039,10 @@ mod tests { let (s_t, r_t) = outcome_transition(&transient, registry, MAX_DISPATCH_ATTEMPTS - 1, now, window); assert_eq!(s_t, ClaimState::Terminal); - assert!(r_t, "a one-way row spent on transients retires terminal too"); + assert!( + r_t, + "a one-way row spent on transients retires terminal too" + ); // family_is_one_way is Registry-exactly: feed-shaped transports that // carry durable rows/replies (Notif, WanMsg) are NOT one-way here. @@ -3036,7 +3078,10 @@ mod tests { } assert!(!family_is_one_way(Some(family)), "{family:?}"); } - assert!(!family_is_one_way(None), "an unfamilied stream is not one-way"); + assert!( + !family_is_one_way(None), + "an unfamilied stream is not one-way" + ); } // [unit->REQ-DISPATCH-HYGIENE-TELEMETRY] keyed-record completeness @@ -3069,7 +3114,10 @@ mod tests { // Pre-classification events name the family honestly. let unclassified = dispatch_event(1, 2, None, 0, 3, "breaker-trip", "window_ms=2000"); - assert!(unclassified.contains("family=unclassified"), "{unclassified:?}"); + assert!( + unclassified.contains("family=unclassified"), + "{unclassified:?}" + ); } // [unit->REQ-DISPATCH-HYGIENE-TELEMETRY] the pool bound under a cold @@ -3105,13 +3153,33 @@ mod tests { fn line_endpoint_resolves_each_family_identity_key() { use serde_json::json; let cases = [ - (StreamFamily::Attach, json!({"endpoint_id": "webbie"}), Some("webbie")), - (StreamFamily::Rest, json!({"endpoint": "ling"}), Some("ling")), + ( + StreamFamily::Attach, + json!({"endpoint_id": "webbie"}), + Some("webbie"), + ), + ( + StreamFamily::Rest, + json!({"endpoint": "ling"}), + Some("ling"), + ), (StreamFamily::Xfer, json!({"endpoint": "oak"}), Some("oak")), - (StreamFamily::ShellLink, json!({"owner": "doyle"}), Some("doyle")), - (StreamFamily::WanMsg, json!({"target": "todlando"}), Some("todlando")), + ( + StreamFamily::ShellLink, + json!({"owner": "doyle"}), + Some("doyle"), + ), + ( + StreamFamily::WanMsg, + json!({"target": "todlando"}), + Some("todlando"), + ), // No endpoint concept -> honest None. - (StreamFamily::Sync, json!({"endpoint_id": "x", "endpoint": "x"}), None), + ( + StreamFamily::Sync, + json!({"endpoint_id": "x", "endpoint": "x"}), + None, + ), (StreamFamily::Registry, json!({"target": "x"}), None), // The right family with a blank/missing field -> None, not "". (StreamFamily::Attach, json!({"endpoint_id": ""}), None), @@ -3136,8 +3204,14 @@ mod tests { // An unfinished attach is the live-reconstruction path and must serve. #[test] fn finished_is_terminal_for_attach_only() { - assert!(finished_row_is_terminal(StreamFamily::Attach, true), "detached attach: terminal"); - assert!(!finished_row_is_terminal(StreamFamily::Attach, false), "live attach: reconstruction serves"); + assert!( + finished_row_is_terminal(StreamFamily::Attach, true), + "detached attach: terminal" + ); + assert!( + !finished_row_is_terminal(StreamFamily::Attach, false), + "live attach: reconstruction serves" + ); // Exhaustive over the enum, not a hand-picked list — the previous one named // 10 of the 12 and had already missed DigestPull. for family in StreamFamily::ALL { @@ -3193,12 +3267,18 @@ mod tests { // Under the bound: N chunks accumulate, ZERO commits before EOF; the // finish batch carries every record, kind-split. let mut acc = FeedAccumulator::new(10); - assert!(acc.push(vec![inst("a"), lbl()]).is_none(), "chunk 1: pooled"); + assert!( + acc.push(vec![inst("a"), lbl()]).is_none(), + "chunk 1: pooled" + ); assert!(acc.push(vec![]).is_none(), "an empty chunk commits nothing"); assert!(acc.push(vec![inst("b")]).is_none(), "chunk 3: pooled"); let batch = acc.finish().expect("EOF hands back the one batch"); assert_eq!((batch.updates.len(), batch.labels.len()), (2, 1)); - assert!(acc.finish().is_none(), "nothing pending after the EOF batch"); + assert!( + acc.finish().is_none(), + "nothing pending after the EOF batch" + ); // Oversized feed: the bound trips mid-stream — ceil(records/bound) // batches, memory stays bounded. diff --git a/crates/spt-daemon/src/docshost.rs b/crates/spt-daemon/src/docshost.rs index 340a633a..a504a4cc 100644 --- a/crates/spt-daemon/src/docshost.rs +++ b/crates/spt-daemon/src/docshost.rs @@ -236,7 +236,9 @@ async fn handle( /// caller's loud log); `[::1]:port` is best-effort where the stack offers it. /// Returns the bound v4 address (the resolved-port source for tests binding /// port 0). -async fn bind_loopback(port: u16) -> io::Result<(tokio::net::TcpListener, Option)> { +async fn bind_loopback( + port: u16, +) -> io::Result<(tokio::net::TcpListener, Option)> { let v4 = tokio::net::TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], port))).await?; let actual = v4.local_addr()?.port(); let v6 = tokio::net::TcpListener::bind(("::1", actual)).await.ok(); @@ -340,10 +342,7 @@ mod tests { "/a/%00", "/%zz", ] { - assert!( - sanitize_request_path(bad).is_none(), - "must reject {bad:?}" - ); + assert!(sanitize_request_path(bad).is_none(), "must reject {bad:?}"); } } @@ -365,7 +364,10 @@ mod tests { content_type_for(Path::new("manifest.schema.json")), "application/json" ); - assert_eq!(content_type_for(Path::new("css/chrome.css")), "text/css; charset=utf-8"); + assert_eq!( + content_type_for(Path::new("css/chrome.css")), + "text/css; charset=utf-8" + ); assert_eq!( content_type_for(Path::new("unknown.bin")), "application/octet-stream" @@ -377,24 +379,31 @@ mod tests { assert_eq!(resolve_docs_port(None, None), DEFAULT_DOCS_PORT); assert_eq!(resolve_docs_port(Some(8080), None), 8080); assert_eq!(resolve_docs_port(Some(8080), Some("9999")), 9999); - assert_eq!(resolve_docs_port(Some(8080), Some("not-a-port")), 8080, "malformed env degrades to config"); - assert_eq!(resolve_docs_port(None, Some("0")), DEFAULT_DOCS_PORT, "0 is not a real override"); + assert_eq!( + resolve_docs_port(Some(8080), Some("not-a-port")), + 8080, + "malformed env degrades to config" + ); + assert_eq!( + resolve_docs_port(None, Some("0")), + DEFAULT_DOCS_PORT, + "0 is not a real override" + ); assert_eq!(docs_url(DEFAULT_DOCS_PORT), "http://localhost:5474"); } // [unit->REQ-TEST-DAEMON-EPHEMERAL-ADVISORY-PORTS] #[test] fn rig_ephemeral_docs_port_retires_a_configured_collision() { - let occupied = std::net::TcpListener::bind(("127.0.0.1", 0)) - .expect("hold a real loopback collision"); + let occupied = + std::net::TcpListener::bind(("127.0.0.1", 0)).expect("hold a real loopback collision"); let occupied_port = occupied.local_addr().unwrap().port(); - let selected = - resolve_daemon_docs_port(Some(occupied_port), Some("not-a-port"), true); + let selected = resolve_daemon_docs_port(Some(occupied_port), Some("not-a-port"), true); assert_eq!(selected, 0, "rig posture wins over every fixed-port layer"); let docs = tempfile::tempdir().expect("temp docs root"); - let bound = start(docs.path().to_path_buf(), selected) - .expect("bind an ephemeral docs port"); + let bound = + start(docs.path().to_path_buf(), selected).expect("bind an ephemeral docs port"); assert_ne!(bound, occupied_port); assert_ne!(bound, 0); } diff --git a/crates/spt-daemon/src/drivehub.rs b/crates/spt-daemon/src/drivehub.rs index 0e34a4b0..dc75334a 100644 --- a/crates/spt-daemon/src/drivehub.rs +++ b/crates/spt-daemon/src/drivehub.rs @@ -938,12 +938,7 @@ pub fn attach_write( // [impl->REQ-SHELL-3] // [impl->REQ-ACTIVITY-LINK-PUSH] // [impl->REQ-ATTACH-LINK-PUSH] -pub fn drive_take( - name: &str, - owner: &str, - shell_id: &str, - token: &str, -) -> io::Result { +pub fn drive_take(name: &str, owner: &str, shell_id: &str, token: &str) -> io::Result { let mut conn = connect(name)?; let req = DriveTakeReq { owner: owner.to_string(), @@ -1400,7 +1395,10 @@ mod tests { foreign.starts_with("LAUNCH_REFUSED_FOREIGN_HOME:"), "{foreign}" ); - assert!(no_daemon.starts_with("LAUNCH_ROUTE_NO_DAEMON:"), "{no_daemon}"); + assert!( + no_daemon.starts_with("LAUNCH_ROUTE_NO_DAEMON:"), + "{no_daemon}" + ); assert!( unanswered.starts_with("LAUNCH_ROUTE_UNANSWERED:"), "a daemon that reads the op and answers nothing must be its own diagnosis, \ @@ -1470,8 +1468,8 @@ mod tests { let ack: ShellLaunchAck = serde_json::from_str(r#"{"accepted":true}"#).expect("a bare accept decodes"); assert!(ack.accepted && ack.reason.is_none()); - let refused: ShellLaunchAck = serde_json::from_str(r#"{"accepted":false,"reason":"x"}"#) - .expect("a refusal decodes"); + let refused: ShellLaunchAck = + serde_json::from_str(r#"{"accepted":false,"reason":"x"}"#).expect("a refusal decodes"); assert!(!refused.accepted && refused.reason.as_deref() == Some("x")); let res: ShellLaunchResult = serde_json::from_str(r#"{"pid":42}"#).expect("a pid-only outcome decodes"); diff --git a/crates/spt-daemon/src/effect.rs b/crates/spt-daemon/src/effect.rs index 409a2926..30ee4df0 100644 --- a/crates/spt-daemon/src/effect.rs +++ b/crates/spt-daemon/src/effect.rs @@ -465,35 +465,23 @@ impl EffectJournal { /// Whether `key`'s effect has already been applied + recorded. pub fn is_applied(&self, key: EffectKey) -> bool { - self.lock_recover() - .applied - .contains(&key) + self.lock_recover().applied.contains(&key) } /// A snapshot of the applied-set (for introspection / tests). Unordered. pub fn applied_keys(&self) -> Vec { - self.lock_recover() - .applied - .iter() - .copied() - .collect() + self.lock_recover().applied.iter().copied().collect() } /// Count of distinct effects applied. pub fn applied_count(&self) -> usize { - self.lock_recover() - .applied - .len() + self.lock_recover().applied.len() } /// Keys with an unfinished `PENDING` (broker crashed mid-effect). Empty on the /// brain-crash path; surfaced for the future broker-restart recovery. pub fn pending_keys(&self) -> Vec { - self.lock_recover() - .pending - .iter() - .copied() - .collect() + self.lock_recover().pending.iter().copied().collect() } } @@ -910,11 +898,13 @@ mod tests { let net_key = k(1, 2); assert_eq!( - j.apply_once(pty_key, EffectKind::PtyWrite, || Ok(())).unwrap(), + j.apply_once(pty_key, EffectKind::PtyWrite, || Ok(())) + .unwrap(), Outcome::Applied ); assert_eq!( - j.apply_once(net_key, EffectKind::NetSend, || Ok(())).unwrap(), + j.apply_once(net_key, EffectKind::NetSend, || Ok(())) + .unwrap(), Outcome::Applied ); @@ -945,19 +935,27 @@ mod tests { // PtyWrite is not. Keys are written as "sid op" tokens on the journal line. let text = std::fs::read_to_string(j.path()).expect("read journal file"); // New line shape carries the minter tag: "PENDING 1 cli 2 net-send". - let net_token = format!("{} {} {}", net_key.class, net_key.minter.as_tag(), net_key.op); - let pty_token = format!("{} {} {}", pty_key.class, pty_key.minter.as_tag(), pty_key.op); + let net_token = format!( + "{} {} {}", + net_key.class, + net_key.minter.as_tag(), + net_key.op + ); + let pty_token = format!( + "{} {} {}", + pty_key.class, + pty_key.minter.as_tag(), + pty_key.op + ); assert!( text.lines().any(|l| { - (l.starts_with("PENDING ") || l.starts_with("DONE ")) - && l.contains(&net_token) + (l.starts_with("PENDING ") || l.starts_with("DONE ")) && l.contains(&net_token) }), "the durable NetSend effect must be journaled to disk; file was: {text:?}" ); assert!( !text.lines().any(|l| { - (l.starts_with("PENDING ") || l.starts_with("DONE ")) - && l.contains(&pty_token) + (l.starts_with("PENDING ") || l.starts_with("DONE ")) && l.contains(&pty_token) }), "an ephemeral PtyWrite must NOT pay the durable journal write (no per-\ keystroke fsync) — REQ-HAZARD-EFFECT-JOURNAL-PTY-WEDGE. File was: {text:?}" @@ -1083,7 +1081,10 @@ mod tests { minter: Minter::Rc, op: 3, }; - assert!(j_new.is_applied(rc_key), "new line recovers to the tagged key"); + assert!( + j_new.is_applied(rc_key), + "new line recovers to the tagged key" + ); assert!( !j_new.is_applied(legacy_key), "a new rc line is not a legacy key" @@ -1098,7 +1099,10 @@ mod tests { .unwrap(); let j_mixed = EffectJournal::open(&mixed_path).unwrap(); assert!(j_mixed.is_applied(legacy_key), "mixed: legacy key present"); - assert!(j_mixed.is_applied(new_producer_key), "mixed: cli key present"); + assert!( + j_mixed.is_applied(new_producer_key), + "mixed: cli key present" + ); assert_eq!( j_mixed.applied_count(), 2, @@ -1154,7 +1158,8 @@ mod tests { op: OP, }; assert_eq!( - j.apply_once(replay, EffectKind::NetDial, || Ok(())).unwrap(), + j.apply_once(replay, EffectKind::NetDial, || Ok(())) + .unwrap(), Outcome::Deduped, "a same-minter same-op replay is still deduped" ); @@ -1184,17 +1189,22 @@ mod tests { minter: Minter::Rc, op: colliding_int, }; - assert_ne!(shell_key, rc_key, "same session+int, different minter = distinct key"); + assert_ne!( + shell_key, rc_key, + "same session+int, different minter = distinct key" + ); // Spool delivery lands first (Spool is durable — a real journal write). assert_eq!( - j.apply_once(shell_key, EffectKind::Spool, || Ok(())).unwrap(), + j.apply_once(shell_key, EffectKind::Spool, || Ok(())) + .unwrap(), Outcome::Applied, "the shell spool delivery applies" ); // The rc operator's identically-numbered op must ALSO apply, not dedupe. assert_eq!( - j.apply_once(rc_key, EffectKind::PtyWrite, || Ok(())).unwrap(), + j.apply_once(rc_key, EffectKind::PtyWrite, || Ok(())) + .unwrap(), Outcome::Applied, "the rc operator op must NOT be swallowed by the shell op's key (the bug)" ); @@ -1239,7 +1249,11 @@ mod tests { assert_eq!(out, "healed"); let ops = minted.borrow(); - assert_eq!(ops.len(), 2, "run invoked exactly twice (initial + ONE retry)"); + assert_eq!( + ops.len(), + 2, + "run invoked exactly twice (initial + ONE retry)" + ); assert_eq!(ops[0].minter, Minter::Rc); assert_eq!( ops[1].minter, diff --git a/crates/spt-daemon/src/failedaddr.rs b/crates/spt-daemon/src/failedaddr.rs index 8719cec9..6eebfa7c 100644 --- a/crates/spt-daemon/src/failedaddr.rs +++ b/crates/spt-daemon/src/failedaddr.rs @@ -190,7 +190,10 @@ mod tests { fn matches_the_exact_address_and_no_other() { let mut m = FailedAddrs::default(); m.note_failed("bb", &addr(64094)); - assert!(m.is_failed(&addr(64094)), "the dialed address is remembered"); + assert!( + m.is_failed(&addr(64094)), + "the dialed address is remembered" + ); assert!( !m.is_failed(&addr(62852)), "a DIFFERENT address for the same peer must still resolve" @@ -236,7 +239,10 @@ mod tests { return; }; m.entries.get_mut(&key_of(&addr(64094))).unwrap().at = aged; - assert!(!m.is_failed(&addr(64094)), "expired: no longer a skip reason"); + assert!( + !m.is_failed(&addr(64094)), + "expired: no longer a skip reason" + ); m.note_failed("cc", &addr(7)); assert_eq!(m.len(), 1, "the expired entry is swept on the next write"); } diff --git a/crates/spt-daemon/src/firewall.rs b/crates/spt-daemon/src/firewall.rs index 70bc3c66..fb3fc3ad 100644 --- a/crates/spt-daemon/src/firewall.rs +++ b/crates/spt-daemon/src/firewall.rs @@ -666,8 +666,13 @@ Action: Allow fix, } => { assert!(rule_path.to_lowercase().contains(r"\spt-core\bin\spt.exe")); - assert!(running_path.to_lowercase().contains(r"\target\debug\spt.exe")); - assert!(fix.contains(r"\target\debug\spt.exe"), "the fix repairs onto the BINDER"); + assert!(running_path + .to_lowercase() + .contains(r"\target\debug\spt.exe")); + assert!( + fix.contains(r"\target\debug\spt.exe"), + "the fix repairs onto the BINDER" + ); } other => panic!("expected PathMismatch, got {other:?}"), } @@ -702,7 +707,10 @@ Action: Allow // MISSING: netsh answered "no such rule". First install's arm. match reconcile_decision(&WinProbe::NoRule, &binder, true) { ReconcileAction::Create { command } => { - assert!(command.contains(RULE_NAME), "creates the PRODUCT rule: {command}"); + assert!( + command.contains(RULE_NAME), + "creates the PRODUCT rule: {command}" + ); assert!( command.contains(r"\spt-core\bin\spt.exe"), "admitting the binder being placed: {command}" @@ -759,7 +767,10 @@ Action: Allow } match reconcile_decision(&WinProbe::NoRule, &binder, false) { ReconcileAction::CannotElevate { verdict } => { - assert!(matches!(verdict, InboundVerdict::Missing { .. }), "{verdict:?}") + assert!( + matches!(verdict, InboundVerdict::Missing { .. }), + "{verdict:?}" + ) } other => panic!("expected CannotElevate, got {other:?}"), } @@ -838,7 +849,10 @@ Program: C:\actions-runner\_work\spt-bs-core\spt-bs InboundVerdict::Unknown ); assert_eq!( - decide_windows(&WinProbe::Dump("Rule Name: spt\nAction: Allow\n".into()), &binder), + decide_windows( + &WinProbe::Dump("Rule Name: spt\nAction: Allow\n".into()), + &binder + ), InboundVerdict::Unknown ); assert!(matches!( @@ -864,10 +878,7 @@ Program: C:\actions-runner\_work\spt-bs-core\spt-bs #[test] fn active_ufw_is_decided_against_the_bound_port() { let allowing = FwState::ActiveRules("51820/udp ALLOW Anywhere\n".to_string()); - assert_eq!( - decide_linux(&[(UFW, allowing)], 51820), - InboundVerdict::Ok - ); + assert_eq!(decide_linux(&[(UFW, allowing)], 51820), InboundVerdict::Ok); let other_port = FwState::ActiveRules("22/tcp ALLOW Anywhere\n".to_string()); match decide_linux(&[(UFW, other_port)], 51820) { @@ -916,19 +927,19 @@ Program: C:\actions-runner\_work\spt-bs-core\spt-bs #[test] fn a_live_manager_outranks_its_backend() { let state_of = |name: &str| match name { - UFW => FwState::ActiveOpaque, // on, rules need root + UFW => FwState::ActiveOpaque, // on, rules need root NFTABLES => FwState::ActiveOpaque, // its backend, also unreadable _ => FwState::Absent, }; - let states: Vec<(&str, FwState)> = PROBE_ORDER - .iter() - .map(|n| (*n, state_of(n))) - .collect(); + let states: Vec<(&str, FwState)> = PROBE_ORDER.iter().map(|n| (*n, state_of(n))).collect(); match decide_linux(&states, 51820) { InboundVerdict::Unverified { firewall, check } => { assert_eq!(firewall, UFW, "the manager answers, not its backend"); - assert!(check.contains("ufw status"), "ufw operators get ufw: {check}"); + assert!( + check.contains("ufw status"), + "ufw operators get ufw: {check}" + ); } other => panic!("expected the ufw verdict, got {other:?}"), } @@ -947,7 +958,10 @@ Program: C:\actions-runner\_work\spt-bs-core\spt-bs match decide_linux( &[ (UFW, FwState::Inactive), - (NFTABLES, FwState::ActiveRules("udp dport 22 accept\n".into())), + ( + NFTABLES, + FwState::ActiveRules("udp dport 22 accept\n".into()), + ), ], 51820, ) { diff --git a/crates/spt-daemon/src/forkop.rs b/crates/spt-daemon/src/forkop.rs index f15e6f47..9189b4ab 100644 --- a/crates/spt-daemon/src/forkop.rs +++ b/crates/spt-daemon/src/forkop.rs @@ -79,7 +79,10 @@ pub fn fork_local(source: &str, new_id: &str, subnet: &str, now_unix: u64) -> Fo if let Some(refusal) = spt_store::engineroom::reserved_id_refusal(new_id) { return ForkLocalOutcome::BadRequest(refusal); } - if spt_store::subnet::SubnetStore::load().find(subnet).is_none() { + if spt_store::subnet::SubnetStore::load() + .find(subnet) + .is_none() + { return ForkLocalOutcome::NoSubnet; } let src_perch = perch::resolve_perch_path(source, ParentHint::Infer); diff --git a/crates/spt-daemon/src/harnesshost.rs b/crates/spt-daemon/src/harnesshost.rs index 0645d962..e8923951 100644 --- a/crates/spt-daemon/src/harnesshost.rs +++ b/crates/spt-daemon/src/harnesshost.rs @@ -152,8 +152,8 @@ pub fn prepare_harness_spawn( ); // [impl->REQ-HAZARD-TEMPLATE-ARGV-FILL] tokenize the template then fill each // token so a multi-word/quote/semicolon {key} value is one argv element. - let tokens = - spt_runtime::runtime::fill_template_tokens(&role.command, &keys).map_err(|e| e.to_string())?; + let tokens = spt_runtime::runtime::fill_template_tokens(&role.command, &keys) + .map_err(|e| e.to_string())?; if tokens.is_empty() { return Err("empty session command".into()); } @@ -455,8 +455,10 @@ mod tests { // A freshly minted id round-trips as provisional. assert!(is_provisional_session_id(&mint_session_id())); assert!(is_provisional_session_id("70b5bfa40901b7d4")); // the triage leak sid - // A Claude UUID is NOT provisional (dashes + length). - assert!(!is_provisional_session_id("b4421cf9-1234-5678-9abc-def012345678")); + // A Claude UUID is NOT provisional (dashes + length). + assert!(!is_provisional_session_id( + "b4421cf9-1234-5678-9abc-def012345678" + )); // Length / charset guards. assert!(!is_provisional_session_id("70b5bfa40901b7d")); // 15 chars assert!(!is_provisional_session_id("70b5bfa40901b7d40")); // 17 chars @@ -472,7 +474,8 @@ mod tests { #[test] fn prepare_fills_id_and_session_into_self_command() { let m = harness_manifest("mock-session --id {id} --session-id {session_id}"); - let prepared = prepare_harness_spawn("doyle", "mock", "sess-abc", &m, false, None, None).unwrap(); + let prepared = + prepare_harness_spawn("doyle", "mock", "sess-abc", &m, false, None, None).unwrap(); assert_eq!( prepared.tokens, vec![ @@ -497,7 +500,8 @@ mod tests { ) .unwrap(); let prepared = - prepare_harness_spawn("hall-a", "mock", "s", &m, false, None, Some("ENLYZEAM")).unwrap(); + prepare_harness_spawn("hall-a", "mock", "s", &m, false, None, Some("ENLYZEAM")) + .unwrap(); assert_eq!( prepared.tokens, vec![ @@ -561,7 +565,8 @@ mod tests { .unwrap(); // Shipped + install_dir → single-element argv = absolute resolved path. - let prepared = prepare_harness_spawn("e", "cc", "s", &m, false, Some(&dir_str), None).unwrap(); + let prepared = + prepare_harness_spawn("e", "cc", "s", &m, false, Some(&dir_str), None).unwrap(); assert_eq!( prepared.translation_binary.as_deref(), Some([shipped.to_string_lossy().into_owned()].as_slice()), @@ -577,7 +582,8 @@ mod tests { // install_dir present but file absent → bare fallback (PATH). let empty = tempfile::tempdir().unwrap(); let empty_str = empty.path().to_string_lossy().into_owned(); - let prepared = prepare_harness_spawn("e", "cc", "s", &m, false, Some(&empty_str), None).unwrap(); + let prepared = + prepare_harness_spawn("e", "cc", "s", &m, false, Some(&empty_str), None).unwrap(); assert_eq!( prepared.translation_binary.as_deref(), Some([bare.to_string()].as_slice()), @@ -598,9 +604,16 @@ mod tests { [env.SPT_READ_ONLY]\ndirection = \"read\"\n", ) .unwrap(); - let prepared = prepare_harness_spawn("wall-b", "mock", "abc", &m, false, None, None).unwrap(); - assert_eq!(prepared.env.get("SPT_ENDPOINT_ID").map(String::as_str), Some("wall-b")); - assert_eq!(prepared.env.get("SPT_SESSION").map(String::as_str), Some("sess-abc")); + let prepared = + prepare_harness_spawn("wall-b", "mock", "abc", &m, false, None, None).unwrap(); + assert_eq!( + prepared.env.get("SPT_ENDPOINT_ID").map(String::as_str), + Some("wall-b") + ); + assert_eq!( + prepared.env.get("SPT_SESSION").map(String::as_str), + Some("sess-abc") + ); // A `read` directive injects nothing. assert!(!prepared.env.contains_key("SPT_READ_ONLY")); } @@ -621,7 +634,8 @@ mod tests { [message-idle-translation-binary]\npath = \"cc-spt-idle-translate\"\n", ) .unwrap(); - let prepared = prepare_harness_spawn("wall-a", "cc", "s", &with, false, None, None).unwrap(); + let prepared = + prepare_harness_spawn("wall-a", "cc", "s", &with, false, None, None).unwrap(); assert_eq!( prepared.translation_binary.as_deref(), Some(["cc-spt-idle-translate".to_string()].as_slice()) @@ -639,13 +653,17 @@ mod tests { prepare_harness_spawn("wall-a", "cc", "s", &cmd, false, Some("/opt/cc"), None).unwrap(); let argv = prepared.translation_binary.expect("command argv"); assert_eq!(argv.len(), 2, "program + one arg: {argv:?}"); - assert!(argv[0].ends_with("claude-spt"), "{{adapter_dir}} filled: {argv:?}"); + assert!( + argv[0].ends_with("claude-spt"), + "{{adapter_dir}} filled: {argv:?}" + ); assert!(argv[0].contains("/opt/cc"), "into install_dir: {argv:?}"); assert_eq!(argv[1], "translate"); // absent → None. let without = harness_manifest("claude"); - let prepared = prepare_harness_spawn("wall-a", "mock", "s", &without, false, None, None).unwrap(); + let prepared = + prepare_harness_spawn("wall-a", "mock", "s", &without, false, None, None).unwrap(); assert!(prepared.translation_binary.is_none()); } @@ -661,9 +679,11 @@ mod tests { min_spt_core_version = \"0\"\n\n[shell]\nspawn = 'sh'\n", ) .unwrap(); - assert!(prepare_harness_spawn("e", "sh", "s", &shell, false, None, None) - .unwrap_err() - .contains("not a harness")); + assert!( + prepare_harness_spawn("e", "sh", "s", &shell, false, None, None) + .unwrap_err() + .contains("not a harness") + ); // Harness with no [session.self] refused. let no_self = spt_runtime::Manifest::from_toml_str( @@ -671,15 +691,19 @@ mod tests { min_spt_core_version = \"0\"\n", ) .unwrap(); - assert!(prepare_harness_spawn("e", "h", "s", &no_self, false, None, None) - .unwrap_err() - .contains("no [session.self]")); + assert!( + prepare_harness_spawn("e", "h", "s", &no_self, false, None, None) + .unwrap_err() + .contains("no [session.self]") + ); // Unknown {placeholder} errs naming the key. let bad = harness_manifest("mock-session --id {id} --boom {not_a_key}"); - assert!(prepare_harness_spawn("e", "mock", "s", &bad, false, None, None) - .unwrap_err() - .contains("not_a_key")); + assert!( + prepare_harness_spawn("e", "mock", "s", &bad, false, None, None) + .unwrap_err() + .contains("not_a_key") + ); } /// A harness manifest declaring BOTH `[session.self]` and a DISTINCT @@ -708,8 +732,8 @@ mod tests { ); // is_resume=true → the RESUME template (`--resume`), filled with the id. - let resumed = - prepare_harness_spawn("doyle", "mock", "sess-abc", &m, true, None, None).expect("resume prepares"); + let resumed = prepare_harness_spawn("doyle", "mock", "sess-abc", &m, true, None, None) + .expect("resume prepares"); assert_eq!( resumed.tokens, vec![ @@ -723,8 +747,8 @@ mod tests { ); // is_resume=false → the SELF template (`--session-id`), same catalog. - let fresh = - prepare_harness_spawn("doyle", "mock", "sess-abc", &m, false, None, None).expect("self prepares"); + let fresh = prepare_harness_spawn("doyle", "mock", "sess-abc", &m, false, None, None) + .expect("self prepares"); assert_eq!( fresh.tokens, vec![ diff --git a/crates/spt-daemon/src/inject.rs b/crates/spt-daemon/src/inject.rs index 1c91b2c1..617bbab7 100644 --- a/crates/spt-daemon/src/inject.rs +++ b/crates/spt-daemon/src/inject.rs @@ -138,8 +138,7 @@ fn drain_spool_offering(id: &str, owlery: &Path, native: bool) -> usize { if !is_spt_hosted_no_relay(id, owlery) { return 0; } - let perch_path = - spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); + let perch_path = spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); // [impl->REQ-SPOOL-TAKE-AUDIT] stamp the claim's provenance with the leg that // actually took it — the audit's whole job is answering WHICH leg, and #164's // root was restated off exactly this token. @@ -178,7 +177,11 @@ fn drain_spool_offering(id: &str, owlery: &Path, native: bool) -> usize { // thing anyone reads, and one shared tag across two arms would make "which // leg delivered this" unanswerable from the log — the same question the // audit column exists to answer on the row. - let tag = if native { "NATIVE_PARKED_DRAIN" } else { "IDLE_PARKED_DRAIN" }; + let tag = if native { + "NATIVE_PARKED_DRAIN" + } else { + "IDLE_PARKED_DRAIN" + }; if delivered > 0 { eprintln!("{tag}:{id}: injected {delivered} parked message(s) via translation binary"); } @@ -215,8 +218,7 @@ pub fn has_parked_idle_spool(id: &str, owlery: &Path) -> bool { if !is_spt_hosted_no_relay(id, owlery) { return false; } - let perch_path = - spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); + let perch_path = spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); if !spt_store::perch::resolve_idle_file(id, spt_store::perch::ParentHint::Infer).exists() { return false; } diff --git a/crates/spt-daemon/src/iobus.rs b/crates/spt-daemon/src/iobus.rs index 9565d727..a10c1e12 100644 --- a/crates/spt-daemon/src/iobus.rs +++ b/crates/spt-daemon/src/iobus.rs @@ -70,7 +70,11 @@ pub struct IoEvent { impl IoEvent { /// Build an event with no digest pointer. - pub fn new(owner: impl Into, kind: impl Into, payload: impl Into) -> Self { + pub fn new( + owner: impl Into, + kind: impl Into, + payload: impl Into, + ) -> Self { Self { owner: owner.into(), kind: kind.into(), @@ -473,7 +477,9 @@ mod tests { fn publishing_to_an_empty_bus_is_a_no_op() { let bus = IoBus::new(); assert_eq!(bus.sink_count(), 0); - assert!(bus.publish(&IoEvent::new("x", IO_KIND_USER_INPUT, "p")).is_empty()); + assert!(bus + .publish(&IoEvent::new("x", IO_KIND_USER_INPUT, "p")) + .is_empty()); } // [unit->REQ-IO-EVENT-TAXONOMY] the shell-link sink bounds the payload at @@ -483,7 +489,11 @@ mod tests { fn the_event_keeps_the_full_payload_the_frame_bounds_it() { let long = "z".repeat(IO_PAYLOAD_CAP + 64); let ev = IoEvent::new("todlando", IO_KIND_AGENT_OUTPUT, long.clone()); - assert_eq!(ev.payload.len(), IO_PAYLOAD_CAP + 64, "the observation is unbounded"); + assert_eq!( + ev.payload.len(), + IO_PAYLOAD_CAP + 64, + "the observation is unbounded" + ); let (bounded, truncated) = bound_payload(&ev.payload); assert!(truncated); assert_eq!(bounded.len(), IO_PAYLOAD_CAP); @@ -543,9 +553,16 @@ mod tests { // so it is asserted against a hostile input rather than a well-behaved one. #[test] fn a_boundary_frame_carries_no_body_even_if_the_event_does() { - let ev = IoEvent::new("todlando", spt_proto::boundary::BOUNDARY_KIND_COMPACT, "leak"); + let ev = IoEvent::new( + "todlando", + spt_proto::boundary::BOUNDARY_KIND_COMPACT, + "leak", + ); let frame = compose_frame_for(&ev); - assert!(!frame.contains("leak"), "payload must not reach the wire: {frame}"); + assert!( + !frame.contains("leak"), + "payload must not reach the wire: {frame}" + ); assert_eq!( frame, "" @@ -566,7 +583,10 @@ mod tests { true, ); assert!(span.contains(r#"mid="1""#), "{span}"); - assert!(span.contains(r#"kind="AGENT_OUTPUT""#), "a span is agent output"); + assert!( + span.contains(r#"kind="AGENT_OUTPUT""#), + "a span is agent output" + ); let close = shellchan::compose_io_frame( "todlando", diff --git a/crates/spt-daemon/src/lib.rs b/crates/spt-daemon/src/lib.rs index 7a559126..465acd1f 100644 --- a/crates/spt-daemon/src/lib.rs +++ b/crates/spt-daemon/src/lib.rs @@ -106,6 +106,7 @@ pub mod access; pub mod activity; pub mod adapter_update; +pub mod answerop; pub mod applyhost; pub mod attach; pub mod attachment; @@ -124,16 +125,14 @@ pub mod deelevate; pub mod digest; pub mod digesthub; pub mod digestlink; -pub mod docshost; pub mod dispatch; +pub mod docshost; pub mod drivehub; pub mod effect; pub mod endpoint; pub mod failedaddr; pub mod firewall; -pub mod answerop; pub mod forkop; -pub mod redeemop; pub mod frame; pub mod grants; pub mod harnesshost; @@ -157,13 +156,14 @@ pub mod psyrelay; pub mod pump; pub mod reap; pub mod reconcile; +pub mod redeemop; pub mod registryhost; pub mod relay; pub mod relcache; pub mod release; -pub mod rollback_compat; pub mod resthost; pub mod resting; +pub mod rollback_compat; pub mod sealsync; pub mod seedmap; pub mod seedproofx; @@ -210,27 +210,23 @@ pub use digesthub::{ digest_to_json, follow, pull_snapshot, render_digest, render_update, reproject, serve_digest_control, update_to_json, DigestHub, }; -pub use effect::{ - with_tracing_retry, EffectJournal, EffectKey, EffectKind, Outcome, OP_NO_LONGER_HELD_MARKER, -}; pub use drivehub::{ activity_write, attach_write, drive_clear, drive_take, drive_write, serve_drive_control, shell_launch, DriveHub, LaunchRouteError, }; -pub use tunnelhub::{ - serve_tunnel_control, tunnel_clear, tunnel_ensure, tunnel_recv, tunnel_resolve, tunnel_send, - TunnelEnd, TunnelHub, +pub use effect::{ + with_tracing_retry, EffectJournal, EffectKey, EffectKind, Outcome, OP_NO_LONGER_HELD_MARKER, }; pub use endpoint::{ broker_socket_name, daemon_pid_path, digest_socket_name, drive_socket_name, pump_heartbeat_path, read_pump_health, read_pump_heartbeat, seed_socket_name, tunnel_socket_name, }; -pub use inject::{is_spt_hosted_no_relay, try_spt_hosted_inject}; pub use frame::{ accept_hello, Envelope, HandshakeError, Hello, Role, IPC_PROTOCOL_VERSION, MIN_COMPATIBLE_VERSION, }; +pub use inject::{is_spt_hosted_no_relay, try_spt_hosted_inject}; pub use lifecycle::{BrainLifecycle, PsycheOutcome, TickReport}; pub use linkhost::{ drive_channel_write, drive_shell, ensure_shell_tunnel, launch_shell_daemon_side, relink_shell, @@ -239,15 +235,11 @@ pub use linkhost::{ ShellLinkRequestOutcome, SurvivorProof, }; pub use nethost::{NetConfig, NetHost, NET_EFFECT_SESSION}; -pub use serveprobe::{ - is_serving_subnet, request_subnet_probe, serve_subnet_probe, ServeProbeServeOutcome, -}; pub use notif::{ first_fire, most_recently_active_visible, produce_and_first_fire, produce_consent_notif, - produce_rollback_notif, produce_scoped_and_first_fire, resurface_at_boundary, - FirstFireOutcome, NotifSurfacePolicy, ResurfaceOutcome, NOTIF_KEY_ENGINE_ROOM_PROBE, - NOTIF_KIND_AGENT, NOTIF_KIND_CONSENT, NOTIF_KIND_PSYCHE, NOTIF_KIND_ROLLBACK, - SUPPRESSION_WINDOW_MS, + produce_rollback_notif, produce_scoped_and_first_fire, resurface_at_boundary, FirstFireOutcome, + NotifSurfacePolicy, ResurfaceOutcome, NOTIF_KEY_ENGINE_ROOM_PROBE, NOTIF_KIND_AGENT, + NOTIF_KIND_CONSENT, NOTIF_KIND_PSYCHE, NOTIF_KIND_ROLLBACK, SUPPRESSION_WINDOW_MS, }; pub use notifsync::{apply_notif_feed, emit_notif_feed, NotifApplyVerdict, NotifPolicy}; pub use propagate::{request_update, serve_update, UpdatePullOutcome, UpdateServeOutcome}; @@ -256,29 +248,34 @@ pub use psyrelay::{ }; pub use relay::Relay; pub use relcache::{ReleaseCache, StagedUpdate}; -pub use rollback_compat::PRE_READY_DURABLE_FILES; pub use release::{ current_platform, parse_verifying_key, sha256_hex, verify_artifact, verify_detached, verify_metadata, verify_signature, verify_update_set_artifact, verify_update_set_docs, - verify_update_set_metadata, - RejectReason, - ReleaseMetadata, SignedRelease, SignedUpdateSet, UpdateArtifactMetadata, UpdateDocsMetadata, - UpdateSetMetadata, UpdateSetProvenance, VerifyPolicy, + verify_update_set_metadata, RejectReason, ReleaseMetadata, SignedRelease, SignedUpdateSet, + UpdateArtifactMetadata, UpdateDocsMetadata, UpdateSetMetadata, UpdateSetProvenance, + VerifyPolicy, }; pub use resthost::{request_rest, serve_rest, RestRequestOutcome, RestServeOutcome}; pub use resting::{ apply_event, arm_transition_echo, daemon_rest_event, daemon_rest_event_with_liveness, - effective_auto_suspend, fire_wake_effects, - read_rest, request_freshness_pull, route_rest_event, take_freshness_pull, transition, - write_rest, EdgeReport, RestEvent, RestRecord, RestRoute, RestState, - NOT_A_HOSTED_PERCH_MARKER, PULL_MARKER_FILE, + effective_auto_suspend, fire_wake_effects, read_rest, request_freshness_pull, route_rest_event, + take_freshness_pull, transition, write_rest, EdgeReport, RestEvent, RestRecord, RestRoute, + RestState, NOT_A_HOSTED_PERCH_MARKER, PULL_MARKER_FILE, }; +pub use rollback_compat::PRE_READY_DURABLE_FILES; pub use seedmap::{put_seed, take_seed, SeedRegistry}; +pub use serveprobe::{ + is_serving_subnet, request_subnet_probe, serve_subnet_probe, ServeProbeServeOutcome, +}; pub use sync::{ reconcile_after_sync, request_sync, select_refs, serve_sync, ReconcileWiring, SyncPolicy, SyncPullReport, SyncServeOutcome, }; pub use transport::{DaemonTransport, LocalSocketTransport}; +pub use tunnelhub::{ + serve_tunnel_control, tunnel_clear, tunnel_ensure, tunnel_recv, tunnel_resolve, tunnel_send, + TunnelEnd, TunnelHub, +}; pub use update::{ apply_brain_only, classify, plan_update, plan_verified, plan_verified_update_set, ApplyError, BrokerAbi, ReleaseSpec, UpdateClass, UpdatePlan, BROKER_RESOURCE_ABI, diff --git a/crates/spt-daemon/src/lifecycle.rs b/crates/spt-daemon/src/lifecycle.rs index f831040d..312b5979 100644 --- a/crates/spt-daemon/src/lifecycle.rs +++ b/crates/spt-daemon/src/lifecycle.rs @@ -296,7 +296,6 @@ impl PsycheBudgets { } } - /// The RESERVED EXIT CODE that discriminates a psyche session-not-found failure /// (F-030 W2, FORK-3; W3 doyle amendment — perri's adapter counter accepted) from /// every other turn failure — the ONLY failure that reseeds (clears custody + @@ -696,12 +695,18 @@ impl ManifestCell { /// never holds the read lock across the spawn/blocking call — a concurrent /// [`refresh`](Self::refresh) is never blocked by a long spawn. fn runtime_snapshot(&self) -> ManifestRuntime { - self.runtime.read().unwrap_or_else(|p| p.into_inner()).clone() + self.runtime + .read() + .unwrap_or_else(|p| p.into_inner()) + .clone() } /// A snapshot **clone** of the manifest (guard dropped on return, as above). fn manifest_snapshot(&self) -> Manifest { - self.manifest.read().unwrap_or_else(|p| p.into_inner()).clone() + self.manifest + .read() + .unwrap_or_else(|p| p.into_inner()) + .clone() } /// Swap BOTH the manifest and its runtime to the freshly-installed on-disk @@ -1114,57 +1119,58 @@ impl BrainLifecycle { if let spt_live::pulse::TurnEcho::Fire { aged_by } = turn_echo { note_turn_echo_age_source_once(&self.id, aged_by); } - let (echo_fired, turn_outcome) = - if edge_due || matches!(turn_echo, spt_live::pulse::TurnEcho::Fire { .. }) { - // [impl->REQ-PSYCHE-ROLE-ABSENT-STATUS] SKIP-WITH-LOUD-STATUS, - // decided BEFORE the turn rather than inside its failure - // handling. Letting the absence reach the spawn is what made a - // structural condition arrive as a per-fire turn failure; the - // only way to spend zero strikes is to produce no turn outcome - // at all, which means not running the leg. The commune-sync - // below still fires — it is a different role with its own - // optionality, and coupling them would make one missing role - // silence the other's work. - let turn_res = if self.psyche_role_declared() { - self.clear_psyche_role_absent(); - Some(self.run_psyche_event_turn(session_id, PSYCHE_PULSE_STANDING_PROMPT, None)) - } else { - note_psyche_role_absent_once(&self.id); - self.record_psyche_role_absent(); - None - }; - // releases#113 fork 3: a boundary left the id of the session it - // rotated away from. Read-and-clear it and summarize THAT session - // — the one that just ended and whose delta is otherwise lost — - // instead of the empty one the harness just opened. - // [impl->REQ-ECHO-BOUNDARY-INPUT-BEFORE-ROTATION] - let boundary_sid = spt_store::perch::take_boundary_echo(&self.id, ParentHint::Infer); - let (echo_sid, echo_trigger) = match &boundary_sid { - Some(sid) => (Some(sid.as_str()), "boundary"), - None => (session_id, "pulse"), - }; - let commune_res = self.fire_echo(echo_sid, echo_trigger); - if let Err(e) = &commune_res { - spt_proto::emit_line_err!("PSYCHE_COMMUNE_SYNC_FAIL:{}: {e}", self.id); - } - // A failure if EITHER leg failed; the reason names the failing leg and - // the CLASS rides with it. The turn's failure takes precedence when both - // failed — the shipped precedence, kept deliberately so the reported class - // is deterministic rather than order-of-evaluation luck. The turn's relay - // already happened above regardless of the commune. - // [impl->REQ-PSYCHE-OUTCOME-CLASSIFIED] - let echo_outcome = PsycheOutcome::from_echo(commune_res); - // A SKIPPED turn contributes nothing to the precedence: the fire - // still reports its commune-sync outcome, so a failing echo is - // still counted, and the absent role adds no strike of its own. - let outcome = match turn_res { - Some(t) if !t.is_ok() => t, - _ => echo_outcome, - }; - (true, Some(outcome)) + let (echo_fired, turn_outcome) = if edge_due + || matches!(turn_echo, spt_live::pulse::TurnEcho::Fire { .. }) + { + // [impl->REQ-PSYCHE-ROLE-ABSENT-STATUS] SKIP-WITH-LOUD-STATUS, + // decided BEFORE the turn rather than inside its failure + // handling. Letting the absence reach the spawn is what made a + // structural condition arrive as a per-fire turn failure; the + // only way to spend zero strikes is to produce no turn outcome + // at all, which means not running the leg. The commune-sync + // below still fires — it is a different role with its own + // optionality, and coupling them would make one missing role + // silence the other's work. + let turn_res = if self.psyche_role_declared() { + self.clear_psyche_role_absent(); + Some(self.run_psyche_event_turn(session_id, PSYCHE_PULSE_STANDING_PROMPT, None)) } else { - (false, None) + note_psyche_role_absent_once(&self.id); + self.record_psyche_role_absent(); + None }; + // releases#113 fork 3: a boundary left the id of the session it + // rotated away from. Read-and-clear it and summarize THAT session + // — the one that just ended and whose delta is otherwise lost — + // instead of the empty one the harness just opened. + // [impl->REQ-ECHO-BOUNDARY-INPUT-BEFORE-ROTATION] + let boundary_sid = spt_store::perch::take_boundary_echo(&self.id, ParentHint::Infer); + let (echo_sid, echo_trigger) = match &boundary_sid { + Some(sid) => (Some(sid.as_str()), "boundary"), + None => (session_id, "pulse"), + }; + let commune_res = self.fire_echo(echo_sid, echo_trigger); + if let Err(e) = &commune_res { + spt_proto::emit_line_err!("PSYCHE_COMMUNE_SYNC_FAIL:{}: {e}", self.id); + } + // A failure if EITHER leg failed; the reason names the failing leg and + // the CLASS rides with it. The turn's failure takes precedence when both + // failed — the shipped precedence, kept deliberately so the reported class + // is deterministic rather than order-of-evaluation luck. The turn's relay + // already happened above regardless of the commune. + // [impl->REQ-PSYCHE-OUTCOME-CLASSIFIED] + let echo_outcome = PsycheOutcome::from_echo(commune_res); + // A SKIPPED turn contributes nothing to the precedence: the fire + // still reports its commune-sync outcome, so a failing echo is + // still counted, and the absent role adds no strike of its own. + let outcome = match turn_res { + Some(t) if !t.is_ok() => t, + _ => echo_outcome, + }; + (true, Some(outcome)) + } else { + (false, None) + }; Ok(TickReport { ingested, echo_fired, @@ -1207,8 +1213,8 @@ impl BrainLifecycle { let interval_ms = self.cfg.pulse_period.as_millis() as u64; // A disk error must not stop the pulse: degrade to an in-memory anchor at // `now` (fresh-phase, unpersisted) so cadence continues regardless. - let anchor = DeadlineAnchor::open(key, interval_ms, reason, now_ms()) - .unwrap_or(DeadlineAnchor { + let anchor = + DeadlineAnchor::open(key, interval_ms, reason, now_ms()).unwrap_or(DeadlineAnchor { anchor_ms: now_ms(), interval_ms: interval_ms.max(1), }); @@ -1336,7 +1342,10 @@ impl BrainLifecycle { now_ms(), // Report-only path: this leg does not feed a health budget, so the // classification is dropped deliberately at THIS boundary (not before it). - || self.fire_echo(session_id, "rest-transition").map_err(|e| e.to_string()), + || { + self.fire_echo(session_id, "rest-transition") + .map_err(|e| e.to_string()) + }, || self.fire_wake_effects(), )?; // The shell leg of the edge (M5-D4a): suspend closes online shells, @@ -1379,7 +1388,11 @@ impl BrainLifecycle { /// ingest leg and `psyche_drop_file` already use — and the summarizer spawn gets /// the endpoint's cwd as its default working dir (a role-declared cwd wins). // [impl->REQ-ECHO-DROP-DIR-RESOLVE] - fn fire_echo(&self, session_id: Option<&str>, trigger: &str) -> Result<(), spt_live::EchoError> { + fn fire_echo( + &self, + session_id: Option<&str>, + trigger: &str, + ) -> Result<(), spt_live::EchoError> { let Some(raw) = &self.commune_dir else { return Ok(()); }; @@ -1589,9 +1602,7 @@ impl BrainLifecycle { // [impl->REQ-PSYCHE-EPHEMERAL-DRIVER] // [impl->REQ-PSYCHE-INVOCATION-BUDGET-PER-ROLE] fn event_turn_timeout(&self) -> Duration { - spt_runtime::invocation_budget( - self.cell.manifest_snapshot().session.psyche_resume.as_ref(), - ) + spt_runtime::invocation_budget(self.cell.manifest_snapshot().session.psyche_resume.as_ref()) } /// The agent's OWN subnet — the parent endpoint's `home_subnet` (info.json), @@ -1702,12 +1713,10 @@ impl BrainLifecycle { // psyche lands in the DEFAULT account root → headless "Not logged in" → strike // loop (flynn's field death). Harness-agnostic: whatever was captured is // forwarded verbatim; core knows no var by name. - let parent_read_env = spt_store::info::read_info(&perch::resolve_perch_path( - &self.id, - ParentHint::Infer, - )) - .map(|r| r.read_env) - .unwrap_or_default(); + let parent_read_env = + spt_store::info::read_info(&perch::resolve_perch_path(&self.id, ParentHint::Infer)) + .map(|r| r.read_env) + .unwrap_or_default(); let runtime = self .cell .runtime_snapshot() @@ -1754,7 +1763,8 @@ impl BrainLifecycle { } None => { let minted = spt_store::psyche_custody::mint_uuid_v4(); - if let Err(e) = spt_store::psyche_custody::write_psyche_sid(&psyche_perch, &minted) { + if let Err(e) = spt_store::psyche_custody::write_psyche_sid(&psyche_perch, &minted) + { // Loud but non-fatal: the turn still runs on the minted id; a next // fire re-mints (custody still None). No first-ever-mint PSYCHE_RESEED — // that marker fires ONLY at a real reseed (custody-clear on @@ -2425,7 +2435,10 @@ keys=[] let perch_path = seed_supervised_perch("doyle", std::process::id()); let out = host.fire_echo(None, "pulse"); - assert!(out.is_err(), "the fixture's summarizer fails, writing no drop"); + assert!( + out.is_err(), + "the fixture's summarizer fails, writing no drop" + ); assert!( !drops.path().join("doyle-commune.md").exists(), "and there is genuinely no artifact — the case the marker exists for" @@ -2535,7 +2548,10 @@ keys=[] #[test] fn psyche_turn_strikes_exhausted_boundary() { assert!(!psyche_turn_strikes_exhausted(0, 3)); - assert!(!psyche_turn_strikes_exhausted(2, 3), "under budget → tolerated"); + assert!( + !psyche_turn_strikes_exhausted(2, 3), + "under budget → tolerated" + ); assert!(psyche_turn_strikes_exhausted(3, 3), "AT budget → fault"); assert!(psyche_turn_strikes_exhausted(4, 3), "past budget → fault"); // Budget of 1 (the forced-fault int knob): the first failure is the fault. @@ -2597,7 +2613,11 @@ keys=[] reason.contains("timed out") && reason.contains("not a defect"), "the stamp names the CLASS so a load signal is not read as a defect: {reason}" ); - assert_eq!(host.budgets_snapshot().timeouts, 0, "bounded re-stamp resets the counter"); + assert_eq!( + host.budgets_snapshot().timeouts, + 0, + "bounded re-stamp resets the counter" + ); }); } @@ -2621,9 +2641,18 @@ keys=[] let (_perch, _stamp) = seeded_stamp_probe("doyle"); // A standing turn-hard counter, and some turn timeouts. - host.note_outcome(PsycheKind::Turn, &PsycheOutcome::Hard("turn defect".to_string())); - host.note_outcome(PsycheKind::Turn, &PsycheOutcome::Timeout("kill".to_string())); - host.note_outcome(PsycheKind::Turn, &PsycheOutcome::Timeout("kill".to_string())); + host.note_outcome( + PsycheKind::Turn, + &PsycheOutcome::Hard("turn defect".to_string()), + ); + host.note_outcome( + PsycheKind::Turn, + &PsycheOutcome::Timeout("kill".to_string()), + ); + host.note_outcome( + PsycheKind::Turn, + &PsycheOutcome::Timeout("kill".to_string()), + ); let snap = host.budgets_snapshot(); assert_eq!((snap.timeouts, snap.hard_turn), (2, 1)); @@ -2874,14 +2903,25 @@ keys=[] // The third consecutive failure exhausts the budget → stamp + reset. host.note_outcome(PsycheKind::Turn, &fail); - assert_eq!(host.budgets_snapshot().hard_turn, 0, "counter resets after the give-up stamp"); + assert_eq!( + host.budgets_snapshot().hard_turn, + 0, + "counter resets after the give-up stamp" + ); let s = stamp().expect("exhaustion stamps psyche_host_error"); - assert!(s.reason.contains("3x consecutively"), "stamp names the rate: {}", s.reason); + assert!( + s.reason.contains("3x consecutively"), + "stamp names the rate: {}", + s.reason + ); // A clean fire clears the stamp and keeps the counter at 0. host.note_outcome(PsycheKind::Turn, &PsycheOutcome::Ok); assert_eq!(host.budgets_snapshot().hard_turn, 0); - assert!(stamp().is_none(), "a successful turn clears the prior fault stamp"); + assert!( + stamp().is_none(), + "a successful turn clears the prior fault stamp" + ); }); } @@ -2984,13 +3024,20 @@ keys=[] !first.contains_key("psyche_context"), "the W3 {{psyche_context}} body key is REPLACED by {{psyche_context_file}}" ); - assert_eq!(first.get("id").map(String::as_str), Some("doyle"), "base keys kept"); + assert_eq!( + first.get("id").map(String::as_str), + Some("doyle"), + "base keys kept" + ); assert_eq!(first.get("node").map(String::as_str), Some("kitsubito")); // A continue turn carries the SAME path key (the discriminator is the file // content, not the key) — the sid stays the psyche's own. let later = psyche_turn_keys(base(), Some("parent-sid"), "psyche-uuid", ctx); - assert_eq!(later.get("session_id").map(String::as_str), Some("psyche-uuid")); + assert_eq!( + later.get("session_id").map(String::as_str), + Some("psyche-uuid") + ); assert_eq!( later.get("psyche_context_file").map(String::as_str), Some(ctx.to_string_lossy().as_ref()) @@ -3063,15 +3110,22 @@ keys=[] ); // FRESH with a real mind: the composed body, non-empty. - let fresh = write_psyche_context_file(&perch, first_turn_psyche_context(Some("MIND"))).unwrap(); + let fresh = + write_psyche_context_file(&perch, first_turn_psyche_context(Some("MIND"))).unwrap(); assert_eq!(std::fs::read_to_string(&fresh).unwrap(), "MIND"); assert!(std::fs::metadata(&fresh).unwrap().len() > 0); // FRESH with a zero-context agent: the NON-EMPTY marker (never // 0-byte — else it would masquerade as continue). Overwrite-in-place: same path. let marker = write_psyche_context_file(&perch, first_turn_psyche_context(None)).unwrap(); - assert_eq!(marker, cont, "overwrite in place — same nested-perch path each turn"); - assert_eq!(std::fs::read_to_string(&marker).unwrap(), PSYCHE_FRESH_MARKER); + assert_eq!( + marker, cont, + "overwrite in place — same nested-perch path each turn" + ); + assert_eq!( + std::fs::read_to_string(&marker).unwrap(), + PSYCHE_FRESH_MARKER + ); assert!(std::fs::metadata(&marker).unwrap().len() > 0); } @@ -3150,7 +3204,13 @@ keys=[] std::fs::create_dir_all(&parent).unwrap(); write_info( &parent, - &InfoJson::new("doyle", "t", std::process::id(), "parent-sid-1", "live_agent"), + &InfoJson::new( + "doyle", + "t", + std::process::id(), + "parent-sid-1", + "live_agent", + ), ) .unwrap(); let psyche_perch = @@ -3160,7 +3220,10 @@ keys=[] assert_eq!(custody::read_psyche_sid(&psyche_perch), None); let minted = custody::mint_uuid_v4(); custody::write_psyche_sid(&psyche_perch, &minted).unwrap(); - assert_eq!(custody::read_psyche_sid(&psyche_perch).as_deref(), Some(minted.as_str())); + assert_eq!( + custody::read_psyche_sid(&psyche_perch).as_deref(), + Some(minted.as_str()) + ); // A parent /clear boundary rotates ONLY the parent perch's sid (exactly // cmd_boundary's core mutation) — the nested custody sid is untouched. @@ -3197,8 +3260,15 @@ keys=[] "/home/x/projects/spt-core" }); // Absolute passes through unchanged, cwd irrelevant. - let abs = Path::new(if cfg!(windows) { "C:/abs/drop" } else { "/abs/drop" }); - assert_eq!(resolve_endpoint_drop_dir(abs, Some(cwd)).as_deref(), Some(abs)); + let abs = Path::new(if cfg!(windows) { + "C:/abs/drop" + } else { + "/abs/drop" + }); + assert_eq!( + resolve_endpoint_drop_dir(abs, Some(cwd)).as_deref(), + Some(abs) + ); assert_eq!(resolve_endpoint_drop_dir(abs, None).as_deref(), Some(abs)); // Relative resolves UNDER the endpoint cwd (the manifest's ".claude"). assert_eq!( @@ -3250,10 +3320,16 @@ keys=[] // ── External: still mints its own project ──────────────────────────── // The direction that fails if the widening ever becomes "always internal". - assert!(!is_spt_internal(Path::new("C:/Users/x/Documents/projects/spt-core"), home)); + assert!(!is_spt_internal( + Path::new("C:/Users/x/Documents/projects/spt-core"), + home + )); // A prefix look-alike is a DIFFERENT directory — the check is path-segment // shaped, not a raw `starts_with` on the string. - assert!(!is_spt_internal(Path::new("C:/Users/x/AppData/Local/spt-coreXYZ"), home)); + assert!(!is_spt_internal( + Path::new("C:/Users/x/AppData/Local/spt-coreXYZ"), + home + )); } // [int->REQ-STORE-CONTEXT-BRANCH-FILL] use-it-like-a-human: a REAL pulse tick with @@ -3419,15 +3495,13 @@ keys=[] #[cfg(windows)] let command = { let script = home.join("mark.bat"); - std::fs::write(&script, format!("@echo ran>\"{}\"\r\n", marker.display())) - .unwrap(); + std::fs::write(&script, format!("@echo ran>\"{}\"\r\n", marker.display())).unwrap(); format!("cmd /C \"{}\"", script.display()) }; #[cfg(unix)] let command = { let script = home.join("mark.sh"); - std::fs::write(&script, format!("echo ran > \"{}\"\n", marker.display())) - .unwrap(); + std::fs::write(&script, format!("echo ran > \"{}\"\n", marker.display())).unwrap(); format!("sh {}", script.display()) }; let toml = format!( @@ -3636,7 +3710,9 @@ keys=[] ); host.note_success(PsycheKind::Turn); assert_eq!( - spt_store::info::read_info(&perch_path).unwrap().psyche_host_error, + spt_store::info::read_info(&perch_path) + .unwrap() + .psyche_host_error, None, "an unknown-kind fault is still cleared by any success (pre-#115 behaviour kept)" ); @@ -4032,7 +4108,9 @@ keys=[] }; let anchor_of = || { let raw = std::fs::read_to_string(crate::deadline::anchor_path("pulse")).unwrap(); - serde_json::from_str::(&raw).unwrap().anchor_ms + serde_json::from_str::(&raw) + .unwrap() + .anchor_ms }; run(StartReason::Cold); @@ -4040,7 +4118,11 @@ keys=[] // Update keeps the same grid phase (no re-base) even across a restart. run(StartReason::Update); - assert_eq!(anchor_of(), cold_phase, "Update must preserve the grid phase"); + assert_eq!( + anchor_of(), + cold_phase, + "Update must preserve the grid phase" + ); // A crash restart re-bases the anchor to a fresh instant. std::thread::sleep(Duration::from_millis(5)); @@ -4121,7 +4203,9 @@ keys=[] // Canonical stores the wake effects read: a member subnet + one // undismissed notif row doyle has never seen. let mut subnets = spt_store::subnet::SubnetStore::load(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let store = spt_store::notif::NotifStore::open().unwrap(); let mut epochs = spt_store::epoch::EpochSource::load_from(&home.join("test-epochs")); @@ -4525,7 +4609,11 @@ keys=[] "2", "after a transient garbage write, the next valid publish still reloads" ); - assert_eq!(last, host.manifest_disk_hash(), "and `last` finally advances"); + assert_eq!( + last, + host.manifest_disk_hash(), + "and `last` finally advances" + ); }); } @@ -4549,7 +4637,10 @@ keys=[] let mut last: Option = None; host.reload_manifest_if_changed(&mut last); - assert_eq!(last, None, "no install dir ⇒ `last` stays None (clean no-op)"); + assert_eq!( + last, None, + "no install dir ⇒ `last` stays None (clean no-op)" + ); assert_eq!( host.cell.manifest_snapshot().adapter.version, "1", diff --git a/crates/spt-daemon/src/linkhost.rs b/crates/spt-daemon/src/linkhost.rs index 235366cc..98106b28 100644 --- a/crates/spt-daemon/src/linkhost.rs +++ b/crates/spt-daemon/src/linkhost.rs @@ -215,9 +215,14 @@ pub fn act_gate_decide( // `always` prompts unconditionally with allow-always suppressed. let persist_allowed = cap.require_approval == ShellApproval::Remembered; if persist_allowed { - if let GrantDecision::Allowed = - grants::decide(store, &capability, owner, node, qualifier.as_deref(), target) - { + if let GrantDecision::Allowed = grants::decide( + store, + &capability, + owner, + node, + qualifier.as_deref(), + target, + ) { return None; } } @@ -736,7 +741,9 @@ pub fn launch_shell_daemon_side(owlery: &Path, owner: &str, shell_id: &str) -> R // [impl->REQ-SHELL-CLI-SPAWN-JOB-EXPOSURE] let perch = spt_store::perch::resolve_shell_perch_path_in(owlery, owner, &id); if let Some(pid) = shellhost::live_launch_winner(&perch) { - spt_proto::emit_line_err!("SHELL_LAUNCH_STOOD_DOWN:{id}: already launched pid={pid} (online at bind)"); + spt_proto::emit_line_err!( + "SHELL_LAUNCH_STOOD_DOWN:{id}: already launched pid={pid} (online at bind)" + ); return Ok(pid); } let install_dir = @@ -1367,8 +1374,8 @@ mod tests { DEAD_PID.to_string(), ) .unwrap(); - let (relinked, _pid) = - relink_shell(&owlery, "doyle", &id).expect("a corpse must not block its own relink"); + let (relinked, _pid) = relink_shell(&owlery, "doyle", &id) + .expect("a corpse must not block its own relink"); assert_eq!(relinked, id, "recovery keeps the canonical id — no churn"); assert!( @@ -1463,9 +1470,18 @@ mod tests { // gateway-A spawns + owns the shell. let id = shellinfo::spawn_record(&owlery, "playdate-gw-a", "Trivial", Some("Scout")) .expect("mint"); - let (out, _) = - run_action(&owlery, "playdate-gw-a", "Scout", SHELL_LINK_RELINK, &[], "op1"); - assert!(matches!(out, ShellLinkServeOutcome::Ok(_)), "relink: {out:?}"); + let (out, _) = run_action( + &owlery, + "playdate-gw-a", + "Scout", + SHELL_LINK_RELINK, + &[], + "op1", + ); + assert!( + matches!(out, ShellLinkServeOutcome::Ok(_)), + "relink: {out:?}" + ); // resolve_link_target — the shared front half of cmd/drive/tunnel/ // relink — resolves the gateway owner's shell opaquely (no type gate). @@ -1475,9 +1491,18 @@ mod tests { // ...and drives a command through identically to an agent owner. let args = vec!["note".to_string(), "hi".to_string()]; - let (out, _) = - run_action(&owlery, "playdate-gw-a", "Scout", SHELL_LINK_CMD, &args, "op2"); - assert!(matches!(out, ShellLinkServeOutcome::Ok(_)), "gateway cmd: {out:?}"); + let (out, _) = run_action( + &owlery, + "playdate-gw-a", + "Scout", + SHELL_LINK_CMD, + &args, + "op2", + ); + assert!( + matches!(out, ShellLinkServeOutcome::Ok(_)), + "gateway cmd: {out:?}" + ); // Exclusivity keys on the owner ENDPOINT-ID, not the type: gateway-B // (same type="gateway", different id) resolves NOTHING for the same @@ -1489,8 +1514,14 @@ mod tests { ), "a same-type different-id owner resolves no shell (id-scoped, not type-scoped)" ); - let (out, reply) = - run_action(&owlery, "playdate-gw-b", "Scout", SHELL_LINK_CMD, &args, "op3"); + let (out, reply) = run_action( + &owlery, + "playdate-gw-b", + "Scout", + SHELL_LINK_CMD, + &args, + "op3", + ); assert!(matches!(out, ShellLinkServeOutcome::Failed(_)), "{out:?}"); assert!( matches!(reply, ShellLinkRecord::Reply { outcome, .. } if outcome == "no_shell"), @@ -1506,7 +1537,11 @@ mod tests { let spawn = "cmd /C exit 0"; #[cfg(unix)] let spawn = "true"; - let p = if persistent { "persistent = true\n" } else { "" }; + let p = if persistent { + "persistent = true\n" + } else { + "" + }; let src = perch::spt_home().join("srcs").join(name); std::fs::create_dir_all(&src).unwrap(); std::fs::write( @@ -1541,7 +1576,9 @@ mod tests { other => panic!("offline must drop, got {other:?}"), } assert!( - spt_store::spool::peek_all_at(&perch_path).unwrap().is_empty(), + spt_store::spool::peek_all_at(&perch_path) + .unwrap() + .is_empty(), "an offline drive drop never spools" ); @@ -1565,11 +1602,17 @@ mod tests { std::fs::write(perch_path.join(shellhost::SHELL_PID_FILE), live.to_string()).unwrap(); shellinfo::record_shell_launch(&perch_path, live, 1_000); match prepare_drive(&owlery, "doyle", "Stick", "stick", "x=0.7,y=-0.2").unwrap() { - DrivePrep::Deliver { id: d, token, frame } => { + DrivePrep::Deliver { + id: d, + token, + frame, + } => { assert_eq!(d, id); assert!(!token.is_empty(), "the parked link token is the stamp"); assert!( - frame.starts_with(""), + frame.starts_with( + "" + ), "{frame}" ); assert!(frame.contains("x=0.7,y=-0.2")); @@ -1612,11 +1655,15 @@ mod tests { ); let args = vec!["stick".to_string(), "x=0.5".to_string()]; - let (out, reply) = run_action(&owlery, "doyle", "Stick", SHELL_LINK_DRIVE, &args, "op1"); + let (out, reply) = + run_action(&owlery, "doyle", "Stick", SHELL_LINK_DRIVE, &args, "op1"); let ShellLinkServeOutcome::Ok(detail) = &out else { panic!("offline drive is a defined drop (ok), got {out:?}") }; - assert!(detail.contains("dropped") && detail.contains("offline"), "{detail}"); + assert!( + detail.contains("dropped") && detail.contains("offline"), + "{detail}" + ); assert!(matches!(reply, ShellLinkRecord::Reply { outcome, .. } if outcome == "ok")); // D1: NOT woken — no relink fired, so still no token parked. assert!( @@ -1625,7 +1672,9 @@ mod tests { ); // D3: never spooled. assert!( - spt_store::spool::peek_all_at(&perch_path).unwrap().is_empty(), + spt_store::spool::peek_all_at(&perch_path) + .unwrap() + .is_empty(), "the remote drive path makes zero spool call" ); @@ -1633,11 +1682,16 @@ mod tests { let (out, reply) = run_action(&owlery, "mallory", "Stick", SHELL_LINK_DRIVE, &args, "op2"); assert!(matches!(out, ShellLinkServeOutcome::Failed(_)), "{out:?}"); - assert!(matches!(reply, ShellLinkRecord::Reply { outcome, .. } if outcome == "no_shell")); + assert!( + matches!(reply, ShellLinkRecord::Reply { outcome, .. } if outcome == "no_shell") + ); // A drive request with no args is a bad request (needs type+payload). let (out, _) = run_action(&owlery, "doyle", "Stick", SHELL_LINK_DRIVE, &[], "op3"); - assert!(matches!(out, ShellLinkServeOutcome::BadRequest(_)), "{out:?}"); + assert!( + matches!(out, ShellLinkServeOutcome::BadRequest(_)), + "{out:?}" + ); }); } @@ -1669,7 +1723,9 @@ mod tests { let node = "nodehex"; // Ungated `list` → proceed. - assert!(act_gate_decide(&GrantStore::default(), &shell, "list", "gw", node, None).is_none()); + assert!( + act_gate_decide(&GrantStore::default(), &shell, "list", "gw", node, None).is_none() + ); // `remembered` `attach`, no grant → blocked, ask names the scope, and // allow-always may persist (remembered). diff --git a/crates/spt-daemon/src/livehost.rs b/crates/spt-daemon/src/livehost.rs index f23f525a..edd83ea4 100644 --- a/crates/spt-daemon/src/livehost.rs +++ b/crates/spt-daemon/src/livehost.rs @@ -206,25 +206,25 @@ pub fn reconcile_once( let Some(adapter) = info.adapter.as_deref() else { continue; // adapterless endpoint — never live-capable }; - let manifest = match spt_runtime::registry::resolve_option_in(registered, adapters_dir, adapter) - { - Ok(m) => m, - Err(_) => { - // FOLD-IN (A-2, REQ-WAKE-RESUME-LEG): a deregistered adapter on an - // online endpoint was silently skipped — the SAME silent host-failure - // class the resume leg fixes. Stamp the loud host_error REPORT (never - // status — the field is a report, not a liveness input). - // [impl->REQ-WAKE-RESUME-LEG] - let _ = spt_store::info::set_host_error( - &perch, - Some(&format!( - "adapter '{adapter}' is not a registered/active adapter on this \ + let manifest = + match spt_runtime::registry::resolve_option_in(registered, adapters_dir, adapter) { + Ok(m) => m, + Err(_) => { + // FOLD-IN (A-2, REQ-WAKE-RESUME-LEG): a deregistered adapter on an + // online endpoint was silently skipped — the SAME silent host-failure + // class the resume leg fixes. Stamp the loud host_error REPORT (never + // status — the field is a report, not a liveness input). + // [impl->REQ-WAKE-RESUME-LEG] + let _ = spt_store::info::set_host_error( + &perch, + Some(&format!( + "adapter '{adapter}' is not a registered/active adapter on this \ node — register it (spt adapter add)" - )), - ); - continue; - } - }; + )), + ); + continue; + } + }; // [impl->REQ-INSTALL-11] resolve the Psyche role program against the // adapter install dir — the registry record's precise `source_dir`, the // same dir Feature E's api seam uses (mod.rs::resolve_ctx_manifest). The @@ -376,7 +376,9 @@ fn resume_woken_endpoint( // [impl->REQ-RESUME-CUSTODY-IDENTITY] the PAIR test, not a bare-pid probe. let pid_alive = resume_in_flight(perch); // The newest ledger row carries the session to resume + its recorded adapter (D-2). - let last = spt_store::sessions::last_k(perch, 1).into_iter().next_back(); + let last = spt_store::sessions::last_k(perch, 1) + .into_iter() + .next_back(); let last_sid = last.as_ref().map(|e| e.session_id.as_str()); let recorded_adapter = last .as_ref() @@ -385,7 +387,13 @@ fn resume_woken_endpoint( let registered_ok = recorded_adapter.is_some_and(|a| { spt_runtime::registry::resolve_option_in(registered, adapters_dir, a).is_ok() }); - match decide_resume(rest_state, pid_alive, last_sid, recorded_adapter, registered_ok) { + match decide_resume( + rest_state, + pid_alive, + last_sid, + recorded_adapter, + registered_ok, + ) { ResumeAction::Skip | ResumeAction::StandDown => {} ResumeAction::NoResumeMaterial => { spt_proto::emit_line_err!( @@ -438,7 +446,8 @@ fn launch_ledger_resume( reason_tag: &str, ) { let parent = adapter.split(':').next().unwrap_or(adapter); - let manifest = match spt_runtime::registry::resolve_option_in(registered, adapters_dir, adapter) { + let manifest = match spt_runtime::registry::resolve_option_in(registered, adapters_dir, adapter) + { Ok(m) => m, Err(_) => return, // adapter not registered/active — the caller gated on this }; @@ -484,7 +493,9 @@ fn launch_ledger_resume( Err(e) => { let _ = spt_store::info::set_host_error( perch, - Some(&format!("{reason_tag}-resume could not launch the harness: {e}")), + Some(&format!( + "{reason_tag}-resume could not launch the harness: {e}" + )), ); eprintln!("{reason_tag}_RESUME_FAIL:{id}: {e}"); } @@ -598,7 +609,9 @@ pub fn resume_restart_orphaned_endpoints( } RestartResume::Resume => { // Resume material from the newest ledger row (session + adapter + cwd). - let Some(last) = spt_store::sessions::last_k(&perch, 1).into_iter().next_back() + let Some(last) = spt_store::sessions::last_k(&perch, 1) + .into_iter() + .next_back() else { spt_proto::emit_line_err!( "DAEMON_RESTART_RESUME_SKIP:{id}: online spt-hosted but no ledger \ @@ -607,7 +620,9 @@ pub fn resume_restart_orphaned_endpoints( continue; }; let Some(adapter) = last.adapter.as_deref().or(info.adapter.as_deref()) else { - spt_proto::emit_line_err!("DAEMON_RESTART_RESUME_SKIP:{id}: no adapter recorded to resume under"); + spt_proto::emit_line_err!( + "DAEMON_RESTART_RESUME_SKIP:{id}: no adapter recorded to resume under" + ); continue; }; launch_ledger_resume( @@ -654,7 +669,13 @@ fn host_one( lifecycle.run_pulse_loop(Some(&session_id), &stop, reason, |_report| {}); }) }; - set.insert(id, HostedLife { stop, thread: handle }); + set.insert( + id, + HostedLife { + stop, + thread: handle, + }, + ); } /// B2 KEYSTONE — PULL liveness reconcile (REQ-HAZARD-HOSTED-LIVENESS-RECONCILE): @@ -864,13 +885,9 @@ pub fn reconcile_hosted_liveness(owlery: &Path, live_sessions: &BTreeSet // `process_exists` is deliberately NOT used: it answers from the // process table, which is EMPTY on snapshot-less platforms, so it // would regress self-heal to "never guess" there. See its doc. - let pid_alive = spt_store::info::read_pid(&perch) - .map(spt_store::proc::is_process_alive); - if hybrid_self_heal_due( - info.status.as_deref(), - info.controllable, - pid_alive, - ) { + let pid_alive = + spt_store::info::read_pid(&perch).map(spt_store::proc::is_process_alive); + if hybrid_self_heal_due(info.status.as_deref(), info.controllable, pid_alive) { BrainLifecycle::mark_offline(&perch, Some(&info.session_id)); spt_proto::emit_line_err!( "HYBRID_SELFHEAL_OFFLINE:{id}: non-live-agent row was online with a dead pid" @@ -986,9 +1003,13 @@ pub fn reconcile_hosted_liveness(owlery: &Path, live_sessions: &BTreeSet // [impl->REQ-HAZARD-DRIVEN-BY-SELFHEAL] if info.driven_by.is_some() { let _ = spt_store::info::set_driven_by(&perch, None); - spt_proto::emit_line_err!("DRIVEN_BY_SELFHEAL_OFFLINE:{id}: cleared stale driven_by (no session)"); + spt_proto::emit_line_err!( + "DRIVEN_BY_SELFHEAL_OFFLINE:{id}: cleared stale driven_by (no session)" + ); } - spt_proto::emit_line_err!("LIVENESS_RECONCILE_OFFLINE:{id}: no live broker session (dead harness)"); + spt_proto::emit_line_err!( + "LIVENESS_RECONCILE_OFFLINE:{id}: no live broker session (dead harness)" + ); offlined.push(id); } } @@ -1136,7 +1157,10 @@ fn sweep_legacy_resident_psyche_for( // Pin 3 residue: clear the stale ready registration the wrapper wrote (info.json + // `ready` marker) so no dead-pid phantom ready perch is left behind. let _ = std::fs::remove_file(psyche_perch.join("info.json")); - let _ = std::fs::remove_file(perch::resolve_ready_file(&psyche_id, ParentHint::Explicit(id))); + let _ = std::fs::remove_file(perch::resolve_ready_file( + &psyche_id, + ParentHint::Explicit(id), + )); spt_proto::emit_line_err!( "LEGACY_PSYCHE_SWEEP_REAP:{id} pid={pid}: reaped stranded pre-W3 resident psyche \ + cleared its stale `{psyche_id}` ready registration" @@ -1340,7 +1364,8 @@ mod tests { fn seed_live_perch(id: &str, adapter: &str, status: &str) { let perch = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&perch).unwrap(); - let mut rec = spt_store::info::InfoJson::new(id, "t", std::process::id(), "sid-1", "live_agent"); + let mut rec = + spt_store::info::InfoJson::new(id, "t", std::process::id(), "sid-1", "live_agent"); rec.adapter = Some(adapter.to_string()); spt_store::info::write_info(&perch, &rec).unwrap(); spt_store::info::set_status(&perch, status).unwrap(); @@ -1442,7 +1467,7 @@ mod tests { }; seed("held"); // a listener holds it seed("gone"); // nothing holds it - // The listener's registered address — the relay evidence itself. + // The listener's registered address — the relay evidence itself. spt_store::registry::register_address( "held", &"127.0.0.1:65000".parse().expect("addr"), @@ -1460,7 +1485,11 @@ mod tests { !offlined.contains(&"held".to_string()), "a relay-held endpoint is live — demoted, not offlined (offlined: {offlined:?})" ); - assert_eq!(claim("held"), None, "…and its stale broker-PTY claim is retired"); + assert_eq!( + claim("held"), + None, + "…and its stale broker-PTY claim is retired" + ); assert!( offlined.contains(&"gone".to_string()), "the B2 keystone is untouched: sessionless with nothing holding it → OFFLINE" @@ -1517,9 +1546,21 @@ mod tests { Some(spt_store::liveness::STATUS_OFFLINE), "dead harness (no session) → offline" ); - assert_eq!(status("alive").as_deref(), Some(STATUS_ONLINE), "session present → stays"); - assert_eq!(status("relay").as_deref(), Some(STATUS_ONLINE), "relay exempt"); - assert_eq!(status("legacy").as_deref(), Some(STATUS_ONLINE), "legacy None exempt"); + assert_eq!( + status("alive").as_deref(), + Some(STATUS_ONLINE), + "session present → stays" + ); + assert_eq!( + status("relay").as_deref(), + Some(STATUS_ONLINE), + "relay exempt" + ); + assert_eq!( + status("legacy").as_deref(), + Some(STATUS_ONLINE), + "legacy None exempt" + ); assert_eq!( status("ready").as_deref(), Some(STATUS_ONLINE), @@ -1568,7 +1609,10 @@ mod tests { .map(|i| i.controlled) .unwrap_or(false) }; - assert!(!controlled("dead"), "B3: sessionless perch → controlled CLEARED"); + assert!( + !controlled("dead"), + "B3: sessionless perch → controlled CLEARED" + ); assert!(controlled("alive"), "live session → controlled untouched"); assert!( !controlled("relay"), @@ -1614,7 +1658,10 @@ mod tests { let after = spt_store::info::read_info(&perch).unwrap(); assert!(!after.controlled, "controlled cleared on the quirk row"); assert_eq!(after.driven_by, None, "driven_by cleared on the quirk row"); - assert_eq!(after.viewer_count, None, "viewer_count cleared on the quirk row"); + assert_eq!( + after.viewer_count, None, + "viewer_count cleared on the quirk row" + ); assert_eq!( after.status.as_deref(), Some(STATUS_ONLINE), @@ -1631,17 +1678,41 @@ mod tests { #[test] fn hybrid_self_heal_due_table() { // The one due shape. - assert!(hybrid_self_heal_due(Some(STATUS_ONLINE), Some(false), Some(false))); + assert!(hybrid_self_heal_due( + Some(STATUS_ONLINE), + Some(false), + Some(false) + )); // Live pid → not due. - assert!(!hybrid_self_heal_due(Some(STATUS_ONLINE), Some(false), Some(true))); + assert!(!hybrid_self_heal_due( + Some(STATUS_ONLINE), + Some(false), + Some(true) + )); // BUSY/absent pid → never guessed. - assert!(!hybrid_self_heal_due(Some(STATUS_ONLINE), Some(false), None)); + assert!(!hybrid_self_heal_due( + Some(STATUS_ONLINE), + Some(false), + None + )); // Not online → nothing to heal. - assert!(!hybrid_self_heal_due(Some("offline"), Some(false), Some(false))); + assert!(!hybrid_self_heal_due( + Some("offline"), + Some(false), + Some(false) + )); assert!(!hybrid_self_heal_due(None, Some(false), Some(false))); // Gateway (None) / daemon-hosted (Some(true)) → exempt. - assert!(!hybrid_self_heal_due(Some(STATUS_ONLINE), None, Some(false))); - assert!(!hybrid_self_heal_due(Some(STATUS_ONLINE), Some(true), Some(false))); + assert!(!hybrid_self_heal_due( + Some(STATUS_ONLINE), + None, + Some(false) + )); + assert!(!hybrid_self_heal_due( + Some(STATUS_ONLINE), + Some(true), + Some(false) + )); } // [unit->REQ-ENDPOINT-ONLINE-TRUTH] broker-failure never mass-offlines: the @@ -1671,7 +1742,9 @@ mod tests { reconcile_hosted_liveness(&perch::owlery_dir(), &live); } assert_eq!( - spt_store::info::read_info(&perch).and_then(|i| i.status).as_deref(), + spt_store::info::read_info(&perch) + .and_then(|i| i.status) + .as_deref(), Some(STATUS_ONLINE), "broker unreachable → the pass never ran, nothing offlined" ); @@ -1694,8 +1767,13 @@ mod tests { with_home(|_| { let perch = perch::resolve_perch_path("hallb", ParentHint::Infer); std::fs::create_dir_all(&perch).unwrap(); - let mut rec = - spt_store::info::InfoJson::new("hallb", "t", std::process::id(), "sid", "live_agent"); + let mut rec = spt_store::info::InfoJson::new( + "hallb", + "t", + std::process::id(), + "sid", + "live_agent", + ); rec.controllable = Some(true); spt_store::info::write_info(&perch, &rec).unwrap(); // Already OFFLINE (the dead endpoint), yet still stamped controlled + @@ -1712,7 +1790,10 @@ mod tests { ); let after = spt_store::info::read_info(&perch).unwrap(); - assert!(!after.controlled, "sticky controlled reaped on the already-offline dead perch"); + assert!( + !after.controlled, + "sticky controlled reaped on the already-offline dead perch" + ); assert_eq!(after.driven_by, None, "sticky driven_by reaped too"); assert_eq!( after.status.as_deref(), @@ -1741,8 +1822,13 @@ mod tests { let seed_ctrl = |id: &str| { let perch = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&perch).unwrap(); - let mut rec = - spt_store::info::InfoJson::new(id, "t", std::process::id(), "sid-1", "live_agent"); + let mut rec = spt_store::info::InfoJson::new( + id, + "t", + std::process::id(), + "sid-1", + "live_agent", + ); rec.adapter = Some("mock".to_string()); rec.controllable = Some(true); spt_store::info::write_info(&perch, &rec).unwrap(); @@ -1779,8 +1865,16 @@ mod tests { "sessionless controllable perch is offlined at boot, not hosted" ); // The live, session-backed perch stays online and IS hosted. - assert_eq!(status("livee").as_deref(), Some(STATUS_ONLINE), "session-backed stays online"); - assert_eq!(set.len(), 1, "only the session-backed endpoint is hosted (no phantom revival)"); + assert_eq!( + status("livee").as_deref(), + Some(STATUS_ONLINE), + "session-backed stays online" + ); + assert_eq!( + set.len(), + 1, + "only the session-backed endpoint is hosted (no phantom revival)" + ); set.stop_host("livee"); // teardown the driver thread }); @@ -1815,7 +1909,13 @@ mod tests { std::fs::create_dir_all(&lp).unwrap(); spt_store::info::write_info( &lp, - &spt_store::info::InfoJson::new("liveparent", "0", std::process::id(), "sid", "live_agent"), + &spt_store::info::InfoJson::new( + "liveparent", + "0", + std::process::id(), + "sid", + "live_agent", + ), ) .unwrap(); spt_store::info::set_status(&lp, STATUS_ONLINE).unwrap(); @@ -1871,9 +1971,8 @@ mod tests { let perch = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&perch).unwrap(); // controllable NOT set (bind has not run yet — this is the skeleton). - let rec = spt_store::info::InfoJson::new( - id, "t", std::process::id(), "", "live_agent", - ); + let rec = + spt_store::info::InfoJson::new(id, "t", std::process::id(), "", "live_agent"); spt_store::info::write_info(&perch, &rec).unwrap(); spt_store::info::set_status(&perch, STATUS_UNBOUND).unwrap(); }; @@ -1923,9 +2022,7 @@ mod tests { fn reconcile_converges_a_dead_relay_and_spares_a_live_or_unproven_one() { with_home(|_| { let owlery = perch::owlery_dir(); - let addr = |port: u16| { - std::net::SocketAddr::from(([127, 0, 0, 1], port)) - }; + let addr = |port: u16| std::net::SocketAddr::from(([127, 0, 0, 1], port)); // A harness-hosted live-agent row: status=online (stamped by its own // `api listen`), controllable NOT Some(true) (no broker PTY), a // registered relay address and a ready marker — the full ONLINE @@ -1952,7 +2049,11 @@ mod tests { }; const DEAD_PID: u32 = 2_000_000_000; // never a real allocation - seed_relay("relay-dead", spt_store::info::PidValue::Numeric(DEAD_PID), 51001); + seed_relay( + "relay-dead", + spt_store::info::PidValue::Numeric(DEAD_PID), + 51001, + ); seed_relay( "relay-live", spt_store::info::PidValue::Numeric(std::process::id()), @@ -2007,7 +2108,11 @@ mod tests { Some(STATUS_ONLINE), "{spared}: a relay that is not PROVABLY gone stays online" ); - assert_eq!(rest.as_deref(), Some("active"), "{spared}: rest intent untouched"); + assert_eq!( + rest.as_deref(), + Some("active"), + "{spared}: rest intent untouched" + ); assert!(ready, "{spared}: ready marker preserved"); assert!(address, "{spared}: relay address preserved"); } @@ -2025,8 +2130,13 @@ mod tests { // The spt-hosted perch on disk (online-latched, controllable). let perch = perch::resolve_perch_path("wallb", ParentHint::Infer); std::fs::create_dir_all(&perch).unwrap(); - let mut rec = - spt_store::info::InfoJson::new("wallb", "t", std::process::id(), "sid", "live_agent"); + let mut rec = spt_store::info::InfoJson::new( + "wallb", + "t", + std::process::id(), + "sid", + "live_agent", + ); rec.controllable = Some(true); spt_store::info::write_info(&perch, &rec).unwrap(); spt_store::info::set_status(&perch, STATUS_ONLINE).unwrap(); @@ -2092,14 +2202,19 @@ mod tests { // Kill the session; wait for the exit-waiter to reap it from the table. brain.kill_session().unwrap(); assert!( - wait_until(Duration::from_secs(5), || !session_set(&mut brain).contains("wallb")), + wait_until(Duration::from_secs(5), || !session_set(&mut brain) + .contains("wallb")), "killed session leaves the broker table" ); // Now the pull reconcile clears the latch → offline. let live2 = session_set(&mut brain); let offlined = reconcile_hosted_liveness(&perch::owlery_dir(), &live2); - assert_eq!(offlined, vec!["wallb".to_string()], "dead-session perch offlined"); + assert_eq!( + offlined, + vec!["wallb".to_string()], + "dead-session perch offlined" + ); assert_eq!( status("wallb").as_deref(), Some(spt_store::liveness::STATUS_OFFLINE), @@ -2236,7 +2351,11 @@ mod tests { &cfg, StartReason::Crash, ); - assert_eq!(second.len(), 1, "a fresh brain re-hosts the online endpoint"); + assert_eq!( + second.len(), + 1, + "a fresh brain re-hosts the online endpoint" + ); set_then_teardown(&second); }); } @@ -2337,7 +2456,10 @@ mod tests { } std::thread::sleep(std::time::Duration::from_millis(20)); } - assert!(removed, "could not remove the perch dir for the torn-down case"); + assert!( + removed, + "could not remove the perch dir for the torn-down case" + ); run(); assert!(set.is_empty(), "a gone perch dir un-hosts the driver"); }); @@ -2398,7 +2520,10 @@ mod tests { let _ = sibling.kill(); let _ = sibling.wait(); - assert!(real, "the real {{id}} legacy wrapper (basename + cmdline match) is reapable"); + assert!( + real, + "the real {{id}} legacy wrapper (basename + cmdline match) is reapable" + ); assert!( spared, "a same-basename sibling with a DIFFERENT id is SPARED — no wrong-kill on a shared box" @@ -2429,15 +2554,27 @@ mod tests { seed(".live-bin"); seed(".live-bin.old-0"); gc_live_bin_dirs(owlery.path()); - assert!(!perch.join(".live-bin").exists(), "the stranded .live-bin own-copy is GC'd at brain start"); - assert!(!perch.join(".live-bin.old-0").exists(), "prior displaced .live-bin.old litter is swept too"); - assert!(perch.join("info.json").is_file(), "the perch + its info.json are untouched"); + assert!( + !perch.join(".live-bin").exists(), + "the stranded .live-bin own-copy is GC'd at brain start" + ); + assert!( + !perch.join(".live-bin.old-0").exists(), + "prior displaced .live-bin.old litter is swept too" + ); + assert!( + perch.join("info.json").is_file(), + "the perch + its info.json are untouched" + ); // ── Image-locked path: an injected remove that ALWAYS fails → the `.live-bin` is // DISPLACED to a fresh `.live-bin.old*` sibling (not deleted, not errored). ── seed(".live-bin"); gc_live_bin_dirs_with(owlery.path(), &|_| { - Err(std::io::Error::new(std::io::ErrorKind::PermissionDenied, "locked")) + Err(std::io::Error::new( + std::io::ErrorKind::PermissionDenied, + "locked", + )) }); assert!( !perch.join(".live-bin").exists(), @@ -2448,7 +2585,11 @@ mod tests { .flatten() .filter(|e| e.file_name().to_string_lossy().starts_with(".live-bin.old")) .collect(); - assert_eq!(displaced.len(), 1, "the locked own-copy is renamed to exactly one fresh .live-bin.old*"); + assert_eq!( + displaced.len(), + 1, + "the locked own-copy is renamed to exactly one fresh .live-bin.old*" + ); // fresh_live_bin_old never renames OVER a still-mapped prior `.old`. let fresh = fresh_live_bin_old(&perch.join(".live-bin")); @@ -2516,14 +2657,26 @@ mod tests { ); // Woken + registered → Resume{sid,adapter}. assert_eq!( - decide_resume(Some(RestState::Active), false, Some("sid9"), Some("mock"), true), + decide_resume( + Some(RestState::Active), + false, + Some("sid9"), + Some("mock"), + true + ), ResumeAction::Resume { session_id: "sid9".into(), adapter: "mock".into() } ); // Woken + UNREGISTERED recorded adapter → Refuse naming it + the next action. - match decide_resume(Some(RestState::Active), false, Some("sid9"), Some("ghost"), false) { + match decide_resume( + Some(RestState::Active), + false, + Some("sid9"), + Some("ghost"), + false, + ) { ResumeAction::Refuse(msg) => assert!( msg.contains("ghost") && msg.contains("spt adapter add"), "F-1 refuse names the adapter + next action: {msg}" @@ -2557,7 +2710,12 @@ mod tests { "F-1 host_error: {err}" ); assert!(info.status.is_none(), "the resume leg NEVER stamps status"); - assert!(!perch.join(spt_store::resume_custody::RESUME_CUSTODY_FILE).exists(), "refused → no spawn → no resume pid"); + assert!( + !perch + .join(spt_store::resume_custody::RESUME_CUSTODY_FILE) + .exists(), + "refused → no spawn → no resume pid" + ); assert_eq!(set.len(), 0, "nothing hosted"); }); } @@ -2569,8 +2727,13 @@ mod tests { with_home(|_| { let perch = perch::resolve_perch_path("cold", ParentHint::Infer); std::fs::create_dir_all(&perch).unwrap(); - let mut rec = - spt_store::info::InfoJson::new("cold", "t", std::process::id(), "sid", "live_agent"); + let mut rec = spt_store::info::InfoJson::new( + "cold", + "t", + std::process::id(), + "sid", + "live_agent", + ); rec.adapter = Some("mock".into()); spt_store::info::write_info(&perch, &rec).unwrap(); crate::resting::write_rest(&perch, RestState::Active, 0).unwrap(); @@ -2585,8 +2748,16 @@ mod tests { StartReason::Cold, ); let info = spt_store::info::read_info(&perch).unwrap(); - assert!(info.host_error.is_none(), "no material → benign, not an error"); - assert!(!perch.join(spt_store::resume_custody::RESUME_CUSTODY_FILE).exists(), "no spawn"); + assert!( + info.host_error.is_none(), + "no material → benign, not an error" + ); + assert!( + !perch + .join(spt_store::resume_custody::RESUME_CUSTODY_FILE) + .exists(), + "no spawn" + ); assert_eq!(set.len(), 0); }); } @@ -2609,8 +2780,16 @@ mod tests { StartReason::Cold, ); let info = spt_store::info::read_info(&perch).unwrap(); - assert!(info.host_error.is_none(), "not woken → no attempt, no error"); - assert!(!perch.join(spt_store::resume_custody::RESUME_CUSTODY_FILE).exists(), "no spawn"); + assert!( + info.host_error.is_none(), + "not woken → no attempt, no error" + ); + assert!( + !perch + .join(spt_store::resume_custody::RESUME_CUSTODY_FILE) + .exists(), + "no spawn" + ); }); } @@ -2722,9 +2901,18 @@ mod tests { let pid_model = |state: &str, controllable: Option| { state != LIVE_AGENT_STATE && controllable != Some(true) }; - assert!(pid_model("ready_agent", Some(false)), "listen-born ready listener → PID model"); - assert!(pid_model("ready_agent", None), "legacy None ready row → PID model"); - assert!(pid_model("gateway", Some(false)), "a gateway capability stamp → PID model"); + assert!( + pid_model("ready_agent", Some(false)), + "listen-born ready listener → PID model" + ); + assert!( + pid_model("ready_agent", None), + "legacy None ready row → PID model" + ); + assert!( + pid_model("gateway", Some(false)), + "a gateway capability stamp → PID model" + ); // Broker-session-truth rows: controllable==Some(true) (ANY state) → fall through. assert!( !pid_model("ready_agent", Some(true)), diff --git a/crates/spt-daemon/src/msg.rs b/crates/spt-daemon/src/msg.rs index e06afb7e..292e544d 100644 --- a/crates/spt-daemon/src/msg.rs +++ b/crates/spt-daemon/src/msg.rs @@ -1909,9 +1909,12 @@ mod tests { #[test] fn stream_lifetime_is_additive_and_defaults_durable() { // N-1 payload: no lifetime key → Durable. - let legacy: NetStreamOpenReq = - serde_json::from_value(json!({ "conn_id": 7 })).unwrap(); - assert_eq!(legacy.lifetime, StreamLifetime::Durable, "absent = Durable (N-1)"); + let legacy: NetStreamOpenReq = serde_json::from_value(json!({ "conn_id": 7 })).unwrap(); + assert_eq!( + legacy.lifetime, + StreamLifetime::Durable, + "absent = Durable (N-1)" + ); // Durable encodes with the key ABSENT (byte-identical to N-1). let durable = serde_json::to_value(NetStreamOpenReq { @@ -2082,7 +2085,10 @@ mod tests { let back: EndpointInputReq = serde_json::from_value(serde_json::to_value(&req).unwrap()).unwrap(); assert_eq!(back.endpoint, "wall-b"); - assert_eq!(decode_bytes(&back.data_b64).unwrap(), decode_bytes(&req.data_b64).unwrap()); + assert_eq!( + decode_bytes(&back.data_b64).unwrap(), + decode_bytes(&req.data_b64).unwrap() + ); let env = endpoint_injected_envelope("wall-b", true, false); assert_eq!(env.kind, KIND_ENDPOINT_INJECTED); @@ -2186,13 +2192,19 @@ mod tests { serde_json::from_value(endpoint_injected_envelope("wall-b", false, false).payload) .unwrap(); assert!(!idle.delivered); - assert!(!idle.spool_deferred, "an IDLE-window spool hint is non-deferred (relay wakes)"); + assert!( + !idle.spool_deferred, + "an IDLE-window spool hint is non-deferred (relay wakes)" + ); // Delivered: delivered=true (spool_deferred ignored). let delivered: EndpointInjected = serde_json::from_value(endpoint_injected_envelope("wall-b", true, false).payload) .unwrap(); - assert!(delivered.delivered, "a binary-delivered reply carries delivered=true"); + assert!( + delivered.delivered, + "a binary-delivered reply carries delivered=true" + ); // N-1: an old broker omits `spool_deferred` → serde-defaults to false. let n1: EndpointInjected = @@ -2233,7 +2245,10 @@ mod tests { // An EVEN older brain (pre-op_id too — only the two original fields). let oldest = json!({ "session_id": 1, "data_b64": encode_bytes(b"x") }); let req: InputReq = serde_json::from_value(oldest).unwrap(); - assert!(req.ack, "the oldest `input` shape still defaults to ack=true"); + assert!( + req.ack, + "the oldest `input` shape still defaults to ack=true" + ); assert_eq!(req.op_id, None); } @@ -2263,7 +2278,10 @@ mod tests { "ack=false must be serialized explicitly" ); let back: InputReq = serde_json::from_value(wire).unwrap(); - assert!(!back.ack, "ack=false survives the round-trip (no default clobber)"); + assert!( + !back.ack, + "ack=false survives the round-trip (no default clobber)" + ); assert_eq!(back.op_id, Some(42)); // And the acked direction round-trips as `true`. @@ -2274,8 +2292,7 @@ mod tests { minter: None, ack: true, }; - let back: InputReq = - serde_json::from_value(serde_json::to_value(&acked).unwrap()).unwrap(); + let back: InputReq = serde_json::from_value(serde_json::to_value(&acked).unwrap()).unwrap(); assert!(back.ack, "ack=true round-trips as true"); } diff --git a/crates/spt-daemon/src/nethost.rs b/crates/spt-daemon/src/nethost.rs index cc10a235..ab46c2c3 100644 --- a/crates/spt-daemon/src/nethost.rs +++ b/crates/spt-daemon/src/nethost.rs @@ -44,12 +44,13 @@ use spt_proto::identity::{Identity, PublicKey}; use crate::broker::SharedSend; use crate::effect::Minter; -use crate::seedproofx::{prove_membership, MembershipSource, RosterExchange}; use crate::frame::Envelope; use crate::msg::{ net_presence_event_envelope, net_stream_data_envelope, net_stream_eof_envelope, - NetPresenceEvent, NetStreamInfo, PRESENCE_CONNECTED, PRESENCE_DIAL_FAILED, PRESENCE_DISCONNECTED, + NetPresenceEvent, NetStreamInfo, PRESENCE_CONNECTED, PRESENCE_DIAL_FAILED, + PRESENCE_DISCONNECTED, }; +use crate::seedproofx::{prove_membership, MembershipSource, RosterExchange}; /// The reserved [`crate::effect::EffectKey`] session namespace for net-scoped /// effects (a dial has no PTY session). Broker session ids are minted from 1 @@ -674,7 +675,12 @@ impl PresenceLog { /// reply used to carry — now it rides the presence stream so the pump seeds /// `peer-addrs.json` from a non-blocking dial the same way. // [impl->REQ-CONV-1] - fn append_connected(&mut self, conn_id: u64, remote_id_hex: &str, remote_addr: serde_json::Value) { + fn append_connected( + &mut self, + conn_id: u64, + remote_id_hex: &str, + remote_addr: serde_json::Value, + ) { self.push(NetPresenceEvent { seq: 0, kind: PRESENCE_CONNECTED.to_string(), @@ -994,9 +1000,7 @@ impl DialPlan { stage, ) .await - .ok_or_else(|| { - io::Error::other("seed-proof failed: peer is not a subnet member") - })? + .ok_or_else(|| io::Error::other("seed-proof failed: peer is not a subnet member"))? } None => HashSet::new(), }; @@ -1674,7 +1678,10 @@ impl NetHost { /// the `apply_once` closure, so a concurrent deduped replay always finds it). /// The `minter` matches the journal key the broker built (ADR-0034 namespacing). pub fn record_dial_op(&self, minter: Minter, op_id: u64, conn_id: u64) { - self.dial_ops.lock().unwrap().insert((minter, op_id), conn_id); + self.dial_ops + .lock() + .unwrap() + .insert((minter, op_id), conn_id); } /// The connection a journaled dial `(minter, op_id)` opened, if this broker @@ -2185,7 +2192,9 @@ impl NetHost { // A replay write failure poisons the seat writer-side; the next // producer enqueue halt-and-removes it (the T1 discipline). // [impl->REQ-STREAMLOG-SUBSCRIBER-DISCIPLINE] - log.lock().unwrap().begin_attach(Arc::clone(&sub), from_seq)?; + log.lock() + .unwrap() + .begin_attach(Arc::clone(&sub), from_seq)?; Ok(()) } @@ -2312,7 +2321,9 @@ mod tests { // identity equivalence spt-net's endpoint module is built on. let pk = Identity::from_seed(&[7u8; 32]).public_key(); let id = EndpointId::from_bytes(&pk.to_bytes()).expect("valid ed25519 point"); - let relay: RelayUrl = "https://relay.example.invalid./".parse().expect("relay url"); + let relay: RelayUrl = "https://relay.example.invalid./" + .parse() + .expect("relay url"); let addr = EndpointAddr::new(id) .with_relay_url(relay.clone()) .with_ip_addr("10.0.0.7:4711".parse().unwrap()); @@ -2323,7 +2334,11 @@ mod tests { Some(relay.to_string().as_str()), "the relay path is found in what iroh ACTUALLY emits: {json}" ); - assert_eq!(addr_relay_urls(&json).len(), 1, "the direct path is not a relay: {json}"); + assert_eq!( + addr_relay_urls(&json).len(), + 1, + "the direct path is not a relay: {json}" + ); // A relay-less address reports None — the honest diagnosis, not an error. let direct_only = serde_json::to_value( @@ -2334,7 +2349,10 @@ mod tests { // Junk / absent degrades to None, never a panic (status surface). assert_eq!(addr_home_relay(&serde_json::Value::Null), None); - assert_eq!(addr_home_relay(&serde_json::json!({"addrs": "not-an-array"})), None); + assert_eq!( + addr_home_relay(&serde_json::json!({"addrs": "not-an-array"})), + None + ); } fn hermetic(identity: &Identity) -> NetConfig { @@ -2471,7 +2489,9 @@ mod tests { assert_eq!(host.conn_count(), 1, "one loopback conn held"); // open_stream mints the cross-wired pair: operator row + peer row. - let op_stream = host.open_stream(c1, crate::msg::StreamLifetime::Durable).expect("open loopback stream"); + let op_stream = host + .open_stream(c1, crate::msg::StreamLifetime::Durable) + .expect("open loopback stream"); let infos = host.stream_infos(); assert_eq!(infos.len(), 2, "operator + peer rows"); let op = infos @@ -2574,7 +2594,11 @@ mod tests { ret.append(&[i]); } let (bytes, finished) = ret.drain(); - assert_eq!(bytes, (0..8u8).collect::>(), "retentive loses nothing, in order"); + assert_eq!( + bytes, + (0..8u8).collect::>(), + "retentive loses nothing, in order" + ); assert!(!finished); // …and a second drain is empty (the cursor consumed them exactly once). assert_eq!(ret.drain().0, Vec::::new()); @@ -2585,7 +2609,11 @@ mod tests { for i in 0..8u8 { ord.append(&[i]); } - assert_eq!(ord.drain().0, vec![5, 6, 7], "ordinary keeps only the last cap chunks"); + assert_eq!( + ord.drain().0, + vec![5, 6, 7], + "ordinary keeps only the last cap chunks" + ); } // [unit->REQ-SHELL-4] the loopback tunnel pair under BACKPRESSURE (M11-W3, @@ -2715,11 +2743,18 @@ mod tests { assert_eq!(log.opener_line(), None, "no newline yet: not pinned"); log.append(b"est\",\"session_id\":3}\n{\"kind\":\"input\"}\n"); let want = &b"{\"kind\":\"request\",\"session_id\":3}"[..]; - assert_eq!(log.opener_line().as_deref(), Some(want), "split line reassembled + pinned"); + assert_eq!( + log.opener_line().as_deref(), + Some(want), + "split line reassembled + pinned" + ); for i in 0..64u32 { log.append(format!("{{\"kind\":\"input\",\"n\":{i}}}\n").as_bytes()); } - assert!(log.floor_seq() > 0, "the bounded ring rolled: seq 0 evicted"); + assert!( + log.floor_seq() > 0, + "the bounded ring rolled: seq 0 evicted" + ); assert_eq!( log.opener_line().as_deref(), Some(want), @@ -2735,7 +2770,11 @@ mod tests { fn opener_capture_gives_up_bounded_on_a_newline_less_stream() { let mut log = StreamLog::new(8, 4); log.append(&vec![b'x'; OPENER_PIN_MAX + 1]); - assert_eq!(log.opener_line(), None, "over the cap without a newline: gave up"); + assert_eq!( + log.opener_line(), + None, + "over the cap without a newline: gave up" + ); log.append(b"late-line\n"); assert_eq!(log.opener_line(), None, "Oversize is terminal"); } @@ -2822,7 +2861,10 @@ mod tests { String::from_utf8_lossy(&got).contains("\"outcome\":\"edge\""), "the reply flushed through the retired row (got {got:?})" ); - assert!(finished, "the reply's FIN reached the requester side (clean end, not torn)"); + assert!( + finished, + "the reply's FIN reached the requester side (clean end, not torn)" + ); } // [unit->REQ-REDISPATCH-FINISHED-RETIRE] a dead CONNECTION retires its @@ -2834,7 +2876,9 @@ mod tests { let a = NetHost::start(hermetic(&Identity::generate())).expect("host a"); let b = NetHost::start(hermetic(&Identity::generate())).expect("host b"); let (conn_id, _) = a.dial(b.addr()).expect("dial"); - let sid = a.open_stream(conn_id, crate::msg::StreamLifetime::Durable).expect("open stream"); + let sid = a + .open_stream(conn_id, crate::msg::StreamLifetime::Durable) + .expect("open stream"); a.send_stream(sid, b"{\"hello\":1}\n", false).expect("send"); // B's acceptor registers the peer row (async — poll). let mut saw = false; @@ -2857,7 +2901,10 @@ mod tests { } std::thread::sleep(Duration::from_millis(10)); } - assert!(swept, "the closed-watcher swept the dead conn's stream rows"); + assert!( + swept, + "the closed-watcher swept the dead conn's stream rows" + ); } // ── ADR-0038 Amendment fixes 2+3+4 — the subscriber-seat discipline at @@ -2933,8 +2980,14 @@ mod tests { // The next producer append sees the poisoned seat: halt-and-remove + // lease cancel — never another write attempt against the dead conn. log.append(b"two"); - assert!(log.subscriber.is_none(), "halt-and-remove at the append site"); - assert!(lease.is_canceled(), "poison cancels the serve lease (fix 4)"); + assert!( + log.subscriber.is_none(), + "halt-and-remove at the append site" + ); + assert!( + lease.is_canceled(), + "poison cancels the serve lease (fix 4)" + ); // Later appends stay seatless (no reinstall, no panic, no re-feed). log.append(b"three"); @@ -2944,7 +2997,8 @@ mod tests { // RENEWS the lease — the old worker's handle stays canceled, fresh // sends serve again. One poison never permanently dead-ends a stream. let (fresh, _cf, _rf) = seat_socket_pair(Duration::from_secs(5)); - log.begin_attach(Arc::clone(&fresh), 0).expect("new generation attaches"); + log.begin_attach(Arc::clone(&fresh), 0) + .expect("new generation attaches"); assert!( !log.lease.is_canceled(), "a new subscriber generation renews the serve lease" @@ -2976,8 +3030,14 @@ mod tests { log.finish(); assert!(log.finished, "the read side still records its clean end"); - assert!(log.subscriber.is_none(), "halt-and-remove at the finish site"); - assert!(lease.is_canceled(), "poison at finish cancels the lease too"); + assert!( + log.subscriber.is_none(), + "halt-and-remove at the finish site" + ); + assert!( + lease.is_canceled(), + "poison at finish cancels the lease too" + ); } // [unit->REQ-STREAMLOG-SUBSCRIBER-DISCIPLINE] @@ -2998,7 +3058,8 @@ mod tests { log.begin_attach(Arc::clone(&a), 0).expect("first attach"); // Healthy prior → displaced (the legit brain-swap path). - log.begin_attach(Arc::clone(&b), 0).expect("healthy displacement"); + log.begin_attach(Arc::clone(&b), 0) + .expect("healthy displacement"); assert!(log.subscriber.as_ref().unwrap().is(&b)); // Poisoned but NOT gone (writer still draining) → refuse WouldBlock. @@ -3011,8 +3072,13 @@ mod tests { assert!(err.to_string().contains("subscriber busy"), "{err}"); // Fully gone → the replacement installs. - log.subscriber.as_ref().unwrap().done.store(true, Ordering::Release); - log.begin_attach(Arc::clone(&a), 0).expect("gone prior admits the replacement"); + log.subscriber + .as_ref() + .unwrap() + .done + .store(true, Ordering::Release); + log.begin_attach(Arc::clone(&a), 0) + .expect("gone prior admits the replacement"); assert!(log.subscriber.as_ref().unwrap().is(&a)); } @@ -3084,7 +3150,8 @@ mod tests { // Pin the wire: nothing the writer does lands until we release. let pin = sub.pin_gate_for_test(); - log.begin_attach(Arc::clone(&sub), 0).expect("attach with a pending replay"); + log.begin_attach(Arc::clone(&sub), 0) + .expect("attach with a pending replay"); // Live appends land while the replay is still entirely undrained. for i in 6..10u8 { log.append(&[i]); // live seqs 6..=9 @@ -3096,7 +3163,11 @@ mod tests { for want in 0u64..10 { let env = crate::codec::read_frame(&mut client).expect("frame on the wire"); assert_eq!(env.kind, crate::msg::KIND_NET_STREAM_DATA); - let seq = env.payload.get("seq").and_then(|v| v.as_u64()).expect("seq"); + let seq = env + .payload + .get("seq") + .and_then(|v| v.as_u64()) + .expect("seq"); assert_eq!( seq, want, "replay-then-live seq order must be structural; a live frame \ @@ -3129,7 +3200,8 @@ mod tests { log.append(b"queued-for-the-displaced-writer"); // HEALTHY displacement: B takes the seat (the brain-swap contract). - log.begin_attach(Arc::clone(&b), 0).expect("healthy displacement"); + log.begin_attach(Arc::clone(&b), 0) + .expect("healthy displacement"); let lease_b = Arc::clone(&log.lease); assert!( !Arc::ptr_eq(&lease_a, &lease_b), @@ -3210,7 +3282,8 @@ mod tests { let (owner, _shell) = host.open_loopback_pair().expect("open pair"); let lease = host.stream_lease(owner).expect("lease handle"); assert!(!lease.is_canceled()); - host.send_stream(owner, b"ok", false).expect("a live lease serves"); + host.send_stream(owner, b"ok", false) + .expect("a live lease serves"); lease.cancel(); let err = host @@ -3271,7 +3344,8 @@ mod tests { let _ = shell; let (a, _ca, _ra) = seat_socket_pair(Duration::from_secs(5)); - host.subscribe_stream(owner, Arc::clone(&a), 0).expect("A subscribes"); + host.subscribe_stream(owner, Arc::clone(&a), 0) + .expect("A subscribes"); let (_, seats) = host.stream_counts(); assert_eq!(seats, 1, "A's seat installed"); @@ -3291,8 +3365,10 @@ mod tests { // Identity rule: B displaces A; A's late unsubscribe must NOT evict B. let (a2, _ca2, _ra2) = seat_socket_pair(Duration::from_secs(5)); let (b, _cb, _rb) = seat_socket_pair(Duration::from_secs(5)); - host.subscribe_stream(owner, Arc::clone(&a2), 0).expect("A2 subscribes"); - host.subscribe_stream(owner, Arc::clone(&b), 0).expect("B displaces A2"); + host.subscribe_stream(owner, Arc::clone(&a2), 0) + .expect("A2 subscribes"); + host.subscribe_stream(owner, Arc::clone(&b), 0) + .expect("B displaces A2"); assert!( !host.unsubscribe_stream(owner, &a2), "a displaced caller's release is a no-op" @@ -3315,7 +3391,8 @@ mod tests { // the retired_row_still_flushes_a_late_reply contract above). let (owner, shell) = host.open_loopback_pair().expect("pair 1"); let (sub, _c, _r) = seat_socket_pair(Duration::from_secs(5)); - host.subscribe_stream(shell, Arc::clone(&sub), 0).expect("subscribe"); + host.subscribe_stream(shell, Arc::clone(&sub), 0) + .expect("subscribe"); let (rows_before, seats_before) = host.stream_counts(); assert_eq!(seats_before, 1); assert!(host.retire_stream(shell)); diff --git a/crates/spt-daemon/src/notif.rs b/crates/spt-daemon/src/notif.rs index f5acc3ba..3ccc2762 100644 --- a/crates/spt-daemon/src/notif.rs +++ b/crates/spt-daemon/src/notif.rs @@ -332,9 +332,9 @@ pub fn first_fire_at( let target = match (&row.to_id, row.scope) { // A node-scoped address resolves on THIS node only, for the same reason // its MRA does: the registry leg is suppressed by an empty map. - (Some(to), NotifScope::Node) => crate::presence::addressed_target( - owlery, &no_regs, local_node, policy, &row.subnet, to, - ), + (Some(to), NotifScope::Node) => { + crate::presence::addressed_target(owlery, &no_regs, local_node, policy, &row.subnet, to) + } (Some(to), NotifScope::Subnet) => { crate::presence::addressed_target(owlery, regs, local_node, policy, &row.subnet, to) } @@ -342,7 +342,11 @@ pub fn first_fire_at( crate::presence::most_recently_active_on_node(owlery, local_node, policy, &row.subnet) } (None, NotifScope::Subnet) => crate::presence::most_recently_active_in_subnet( - owlery, regs, local_node, policy, &row.subnet, + owlery, + regs, + local_node, + policy, + &row.subnet, ), }; let Some(target) = target else { @@ -565,7 +569,8 @@ pub fn render_via_shell_notif_templates(owlery: &Path, endpoint: &str, row: &Not Ok(_pid) => rendered += 1, Err(e) => spt_proto::emit_line_err!( "NOTIF_SHELL_RENDER_DROP:{}:{}: {e}", - row.notif_id, record.name + row.notif_id, + record.name ), } } @@ -1037,7 +1042,10 @@ mod tests { "no fallback: the row is held, not redirected" ); let stored = s.get(&row.notif_id).unwrap().unwrap(); - assert!(stored.seen.is_empty(), "and it stays unseen for the boundary"); + assert!( + stored.seen.is_empty(), + "and it stays unseen for the boundary" + ); assert!(!stored.dismissed); }); } @@ -1471,8 +1479,14 @@ mod tests { // [unit->REQ-NOTIF-SCOPE] [unit->REQ-NOTIF-COALESCE] assert_eq!(row.scope, spt_store::notif::NotifScope::Node); assert_eq!(row.coalesce_key.as_deref(), Some(NOTIF_KEY_ROLLBACK)); - assert!(row.body.contains("v9 failed"), "names the quarantined version"); - assert!(row.body.contains("rolled back to v8"), "names the running version"); + assert!( + row.body.contains("v9 failed"), + "names the quarantined version" + ); + assert!( + row.body.contains("rolled back to v8"), + "names the running version" + ); assert_eq!( fired, FirstFireOutcome::Fired { @@ -1680,12 +1694,26 @@ mod tests { let s = store(home); let mut e = epochs(home); let (_row, fired) = produce_and_first_fire( - &s, "cafe", &mut e, "home", NOTIF_KIND_AGENT, "issuer", "quiet", - &home_policy(), &owlery, 1_000, + &s, + "cafe", + &mut e, + "home", + NOTIF_KIND_AGENT, + "issuer", + "quiet", + &home_policy(), + &owlery, + 1_000, ) .unwrap(); assert!( - matches!(fired, FirstFireOutcome::Fired { delivery: SendOutcome::Queued, .. }), + matches!( + fired, + FirstFireOutcome::Fired { + delivery: SendOutcome::Queued, + .. + } + ), "quiet delivery is always Queued (spool), never a live Sent: {fired:?}" ); // The live event-stream drain sees NOTHING (active_only never rides @@ -1695,7 +1723,11 @@ mod tests { "active_only notif is not on the live stream — no PTY interrupt" ); // ...but the hook-channel drain surfaces it at the boundary. - assert_eq!(spool::drain_all_at(&ling).unwrap().len(), 1, "surfaces at drain"); + assert_eq!( + spool::drain_all_at(&ling).unwrap().len(), + 1, + "surfaces at drain" + ); }); } @@ -1740,8 +1772,15 @@ mod tests { let mut e = epochs(home); let row = s .produce_scoped( - "cafe", &mut e, "home", NOTIF_KIND_CONSENT, "spt-update", "staged", - spt_store::notif::NotifScope::Node, Some(NOTIF_KEY_UPDATE_STAGED), None, + "cafe", + &mut e, + "home", + NOTIF_KIND_CONSENT, + "spt-update", + "staged", + spt_store::notif::NotifScope::Node, + Some(NOTIF_KEY_UPDATE_STAGED), + None, ) .unwrap(); @@ -1755,7 +1794,11 @@ mod tests { }, "node-scoped fires to the local endpoint, never RemoteTarget" ); - assert_eq!(spool::drain_all_at(&ling).unwrap().len(), 1, "delivered locally"); + assert_eq!( + spool::drain_all_at(&ling).unwrap().len(), + 1, + "delivered locally" + ); }); } @@ -1773,16 +1816,29 @@ mod tests { let mut e = epochs(home); let expired = s .produce_scoped( - "cafe", &mut e, "home", NOTIF_KIND_AGENT, "issuer", "stale", - spt_store::notif::NotifScope::Subnet, None, Some(1_000), + "cafe", + &mut e, + "home", + NOTIF_KIND_AGENT, + "issuer", + "stale", + spt_store::notif::NotifScope::Subnet, + None, + Some(1_000), ) .unwrap(); // now_ms past the expiry: the per-subnet sweep dismisses it, so the // undismissed working set is empty and nothing surfaces. - let out = - resurface_at_boundary(&s, "doyle", &home_policy(), &owlery, 5_000, SUPPRESSION_WINDOW_MS) - .unwrap(); + let out = resurface_at_boundary( + &s, + "doyle", + &home_policy(), + &owlery, + 5_000, + SUPPRESSION_WINDOW_MS, + ) + .unwrap(); assert!(out.is_empty(), "expired row swept before undismissed read"); assert!( s.get(&expired.notif_id).unwrap().unwrap().dismissed, @@ -1808,8 +1864,15 @@ mod tests { let mut e = epochs(home); let row = s .produce_scoped( - "cafe", &mut e, "home", NOTIF_KIND_AGENT, "issuer", "stale", - spt_store::notif::NotifScope::Subnet, None, Some(1_000), + "cafe", + &mut e, + "home", + NOTIF_KIND_AGENT, + "issuer", + "stale", + spt_store::notif::NotifScope::Subnet, + None, + Some(1_000), ) .unwrap(); diff --git a/crates/spt-daemon/src/notifgate.rs b/crates/spt-daemon/src/notifgate.rs index 7395a919..629dab3a 100644 --- a/crates/spt-daemon/src/notifgate.rs +++ b/crates/spt-daemon/src/notifgate.rs @@ -234,8 +234,14 @@ mod tests { fn distinct_notifs_both_deliver() { let mut seen = HashSet::new(); let live = |_: &str| true; - assert_eq!(classify(¬ify("a:1", "one"), &mut seen, live), Verdict::Deliver); - assert_eq!(classify(¬ify("b:2", "two"), &mut seen, live), Verdict::Deliver); + assert_eq!( + classify(¬ify("a:1", "one"), &mut seen, live), + Verdict::Deliver + ); + assert_eq!( + classify(¬ify("b:2", "two"), &mut seen, live), + Verdict::Deliver + ); } // [unit->REQ-NOTIF-DRAIN-ROW-VALIDITY] retain_deliverable keeps ORDER and diff --git a/crates/spt-daemon/src/notifsync.rs b/crates/spt-daemon/src/notifsync.rs index d0596eb1..c40b1e92 100644 --- a/crates/spt-daemon/src/notifsync.rs +++ b/crates/spt-daemon/src/notifsync.rs @@ -266,12 +266,26 @@ mod tests { let mut epochs = EpochSource::load_from(&dir.path().join("a-epoch")); let subnet_row = a - .produce("nodea", &mut epochs, "home", "agent", "doyle", "subnet-fact") + .produce( + "nodea", + &mut epochs, + "home", + "agent", + "doyle", + "subnet-fact", + ) .unwrap(); let node_row = a .produce_scoped( - "nodea", &mut epochs, "home", "consent", "spt-update", "node-fact", - NotifScope::Node, Some("spt-core:update-staged"), None, + "nodea", + &mut epochs, + "home", + "consent", + "spt-update", + "node-fact", + NotifScope::Node, + Some("spt-core:update-staged"), + None, ) .unwrap(); @@ -280,14 +294,24 @@ mod tests { .iter() .map(|NotifRecord::Row { row }| row.notif_id.as_str()) .collect(); - assert_eq!(ids, vec![subnet_row.notif_id.as_str()], "only the subnet-scoped row"); - assert!(!ids.contains(&node_row.notif_id.as_str()), "node-scoped excluded"); + assert_eq!( + ids, + vec![subnet_row.notif_id.as_str()], + "only the subnet-scoped row" + ); + assert!( + !ids.contains(&node_row.notif_id.as_str()), + "node-scoped excluded" + ); // And it truly never materializes at a peer that applies the feed. let b = store(dir.path(), "b.db"); let policy_b = trusting(&["home"], "nodea-hex"); apply_notif_feed(&b, "nodea-hex", &records, &policy_b).unwrap(); - assert!(b.get(&node_row.notif_id).unwrap().is_none(), "peer never sees it"); + assert!( + b.get(&node_row.notif_id).unwrap().is_none(), + "peer never sees it" + ); assert_eq!(b.list("home").unwrap().len(), 1); } diff --git a/crates/spt-daemon/src/pairhost.rs b/crates/spt-daemon/src/pairhost.rs index 7b36c7de..52270c1a 100644 --- a/crates/spt-daemon/src/pairhost.rs +++ b/crates/spt-daemon/src/pairhost.rs @@ -129,7 +129,8 @@ pub async fn respond( match roster.save() { Ok(()) => spt_proto::emit_line_err!( "PAIRED: joiner {} recorded in subnet '{}'", - outcome.joiner_hex, outcome.subnet + outcome.joiner_hex, + outcome.subnet ), Err(e) => spt_proto::emit_line_err!("PAIRING_ROSTER_SAVE_FAIL: {e}"), } @@ -137,7 +138,9 @@ pub async fn respond( // A failed ceremony is normal traffic (wrong code, impostor probe, // vanished peer) — logged, never fatal; the limiter charged it. Ok(Err(e)) => spt_proto::emit_line_err!("PAIRING_ATTEMPT_FAIL: {e}"), - Err(_) => spt_proto::emit_line_err!("PAIRING_TIMEOUT: ceremony exceeded {CEREMONY_TIMEOUT_SECS}s"), + Err(_) => { + spt_proto::emit_line_err!("PAIRING_TIMEOUT: ceremony exceeded {CEREMONY_TIMEOUT_SECS}s") + } } // Release the ceremony slot before the close-grace wait — the next // joiner must not be shed at the door for the lame-duck duration of @@ -224,7 +227,9 @@ pub fn spawn_meet_rotation( // step boundary; each failure only ends one exchange. loop { match listener.serve_once(&real_addr).await { - Ok(()) => spt_proto::emit_line_err!("PAIR_MEET_ANSWERED:{name} step={step}"), + Ok(()) => { + spt_proto::emit_line_err!("PAIR_MEET_ANSWERED:{name} step={step}") + } Err(e) => { spt_proto::emit_line_err!("PAIR_MEET_SERVE_ERR:{name}: {e}"); // Endpoint closed or a malformed probe — brief @@ -1056,8 +1061,14 @@ mod tests { let v = meet_failure_detail("IPv4-only", "meet probe timed out", 4, 75, 75, clock, true); assert!(v.contains("4 rendezvous attempt"), "attempt count: {v}"); assert!(v.contains("75s"), "elapsed/deadline: {v}"); - assert!(v.contains("bound families: IPv4-only"), "families (ties W1): {v}"); - assert!(v.contains("last error: meet probe timed out"), "last error kept: {v}"); + assert!( + v.contains("bound families: IPv4-only"), + "families (ties W1): {v}" + ); + assert!( + v.contains("last error: meet probe timed out"), + "last error kept: {v}" + ); // REQ-JOIN-VERBOSE-CLOCK: the joiner's step, signed offset, and // correction state all carried in the verbose block. assert!(v.contains("joiner clock:"), "clock line present: {v}"); @@ -1147,8 +1158,15 @@ mod tests { ) .await; assert_eq!(got, Ok(7u32), "the post-refresh final sweep lands"); - assert_eq!(calls.get(), 2, "one exhausting probe + one post-refresh retry"); - assert!(refreshed.get(), "the refresh hook fired between the two probes"); + assert_eq!( + calls.get(), + 2, + "one exhausting probe + one post-refresh retry" + ); + assert!( + refreshed.get(), + "the refresh hook fired between the two probes" + ); } // [unit->REQ-HAZARD-CEREMONY-CLOCK-STEP] and if the final post-refresh sweep @@ -1172,6 +1190,10 @@ mod tests { ) .await; assert_eq!(got, Err("dead subnet"), "exhaustion error preserved"); - assert_eq!(calls.get(), 2, "exhausting probe + one final retry, then stop"); + assert_eq!( + calls.get(), + 2, + "exhausting probe + one final retry, then stop" + ); } } diff --git a/crates/spt-daemon/src/projwriter.rs b/crates/spt-daemon/src/projwriter.rs index 6d466894..dfab51e2 100644 --- a/crates/spt-daemon/src/projwriter.rs +++ b/crates/spt-daemon/src/projwriter.rs @@ -251,7 +251,10 @@ impl WriterEngine { generated_ms: current.as_ref().map(|i| i.generated_ms).unwrap_or(0), source_generation: last_fingerprint.clone(), pending_refresh: true, // the boot reconcile is queued by definition - endpoints: current.as_ref().map(|i| i.endpoints.len() as u64).unwrap_or(0), + endpoints: current + .as_ref() + .map(|i| i.endpoints.len() as u64) + .unwrap_or(0), ..IndexWriterStats::default() }; stats.projects = current @@ -287,7 +290,8 @@ impl WriterEngine { // re-derives them exactly once. // [impl->REQ-PROJECT-INDEX-INVALIDATION] for cwd in &req.cwds { - self.cwd_cache.remove(&projderive::normalize_path(Path::new(cwd))); + self.cwd_cache + .remove(&projderive::normalize_path(Path::new(cwd))); } // ── 1. ONE branch enumeration → fingerprint ────────────────────── @@ -318,7 +322,11 @@ impl WriterEngine { && req.cwds.is_empty() && self.current.is_some() { - let report = CycleReport { counters, published: false, skipped_unchanged: true }; + let report = CycleReport { + counters, + published: false, + skipped_unchanged: true, + }; self.finish_cycle(&report, now, started.elapsed()); return Ok(report); } @@ -329,8 +337,7 @@ impl WriterEngine { .filter_map(|(b, _)| b.strip_prefix("p-").map(|p| (p.to_string(), b.clone()))) .collect(); if let (false, Some(store)) = (self.branch_order.is_empty(), &store) { - let live: BTreeSet<&str> = - self.branch_order.iter().map(|(_, b)| b.as_str()).collect(); + let live: BTreeSet<&str> = self.branch_order.iter().map(|(_, b)| b.as_str()).collect(); self.branch_cache.retain(|b, _| live.contains(b.as_str())); for (branch, tip) in tips.iter().filter(|(b, _)| b.starts_with("p-")) { let cached = self.branch_cache.get(branch); @@ -348,8 +355,13 @@ impl WriterEngine { (rest == PROJECT_CONTEXT_FILE).then(|| id.to_string()) }) .collect(); - self.branch_cache - .insert(branch.clone(), BranchScan { tip: tip.clone(), members }); + self.branch_cache.insert( + branch.clone(), + BranchScan { + tip: tip.clone(), + members, + }, + ); } } else { self.branch_cache.clear(); @@ -371,7 +383,9 @@ impl WriterEngine { req.endpoints .iter() .filter_map(|id| { - by_id.get(id).map(|(p, c)| (id.clone(), p.clone(), c.clone())) + by_id + .get(id) + .map(|(p, c)| (id.clone(), p.clone(), c.clone())) }) .collect() }; @@ -399,7 +413,12 @@ impl WriterEngine { let (id, display) = spt_store::project::project_id_and_display_for_dir(dir); cache.insert( key, - CwdDerivation { id: id.clone(), display: display.clone(), marker, stamp }, + CwdDerivation { + id: id.clone(), + display: display.clone(), + marker, + stamp, + }, ); (id, display) }; @@ -407,7 +426,10 @@ impl WriterEngine { let mut endpoints: BTreeMap = if full { BTreeMap::new() } else { - self.current.as_ref().map(|i| i.endpoints.clone()).unwrap_or_default() + self.current + .as_ref() + .map(|i| i.endpoints.clone()) + .unwrap_or_default() }; if !full { // A scoped id whose perch vanished (purge) drops its row — the @@ -479,13 +501,19 @@ impl WriterEngine { let mut cwds: BTreeMap = if full { BTreeMap::new() } else { - self.current.as_ref().map(|i| i.cwds.clone()).unwrap_or_default() + self.current + .as_ref() + .map(|i| i.cwds.clone()) + .unwrap_or_default() }; for (norm, entry) in self.cwd_cache.iter() { if !entry.id.is_empty() { cwds.insert( norm.clone(), - projindex::CwdProject { id: entry.id.clone(), display: entry.display.clone() }, + projindex::CwdProject { + id: entry.id.clone(), + display: entry.display.clone(), + }, ); } } @@ -511,7 +539,11 @@ impl WriterEngine { self.stats.projects = distinct_projects(&index) as u64; self.current = Some(index); - let report = CycleReport { counters, published: true, skipped_unchanged: false }; + let report = CycleReport { + counters, + published: true, + skipped_unchanged: false, + }; self.finish_cycle(&report, now, started.elapsed()); Ok(report) } @@ -644,7 +676,10 @@ pub fn spawn_index_writer(stop: Arc) -> JoinHandle<()> { // Boot reconcile: global but NOT forced — a warm start over an // unchanged store exits without a scan (the cold/warm start gate). let boot = projinval::coalesce(projinval::drain_at(&engine.paths.invalidations_dir)); - let boot = Coalesced { global: true, ..boot }; + let boot = Coalesced { + global: true, + ..boot + }; if let Err(e) = engine.reconcile(&boot, false) { engine.record_failure(e); } @@ -681,7 +716,14 @@ pub fn spawn_index_writer(stop: Arc) -> JoinHandle<()> { if due_periodic { since_periodic = Duration::ZERO; } - let req = if due_periodic { Coalesced { global: true, ..req } } else { req }; + let req = if due_periodic { + Coalesced { + global: true, + ..req + } + } else { + req + }; if req.is_empty() && !due_periodic { continue; // a racer consumed it (never happens in production) } @@ -732,7 +774,12 @@ mod tests { invalidations_dir: home.join("index").join("invalidations"), }; std::fs::create_dir_all(&paths.owlery).unwrap(); - Fixture { _tmp: tmp, root, home, paths } + Fixture { + _tmp: tmp, + root, + home, + paths, + } } fn store(&self) -> ContextStore { @@ -767,7 +814,9 @@ mod tests { let cs = self.store(); let file = cs.project_context_path(project, id).unwrap(); std::fs::write(&file, format!("{id} in {project}")).unwrap(); - cs.commit_project(project, &format!("{id} slice")).unwrap().unwrap(); + cs.commit_project(project, &format!("{id} slice")) + .unwrap() + .unwrap(); } /// A plain (non-git) project dir whose folder name becomes the id. @@ -781,7 +830,10 @@ mod tests { } fn global() -> Coalesced { - Coalesced { global: true, ..Coalesced::default() } + Coalesced { + global: true, + ..Coalesced::default() + } } // [unit->REQ-PROJECT-INDEX-WRITER] THE complexity-counter gate (the CI gate @@ -808,7 +860,11 @@ mod tests { assert!(r1.published); assert_eq!( r1.counters, - CycleCounters { branch_enumerations: 1, tree_scans: 2, derivations: 2 }, + CycleCounters { + branch_enumerations: 1, + tree_scans: 2, + derivations: 2 + }, "cold cycle: one enumeration, one scan per p-* branch, one derivation per distinct cwd" ); @@ -818,10 +874,17 @@ mod tests { assert!(r2.published); assert_eq!( r2.counters, - CycleCounters { branch_enumerations: 1, tree_scans: 0, derivations: 0 }, + CycleCounters { + branch_enumerations: 1, + tree_scans: 0, + derivations: 0 + }, "warm full cycle: caches absorb every scan and derivation" ); - assert_eq!(engine.stats.cwd_cache_hits, 2, "both cwds re-answered from cache"); + assert_eq!( + engine.stats.cwd_cache_hits, 2, + "both cwds re-answered from cache" + ); // One branch moves → exactly ONE rescan (≤1 tree scan per CHANGED branch). fx.membership("alpha", "ep3"); @@ -869,11 +932,18 @@ mod tests { // The restarted brain: fresh engine, warm disk. let mut warm = WriterEngine::new(fx.paths.clone()); let r = warm.reconcile(&global(), false).unwrap(); - assert!(r.skipped_unchanged, "unchanged generation → the boot reconcile is a no-op"); + assert!( + r.skipped_unchanged, + "unchanged generation → the boot reconcile is a no-op" + ); assert!(!r.published); assert_eq!( r.counters, - CycleCounters { branch_enumerations: 1, tree_scans: 0, derivations: 0 } + CycleCounters { + branch_enumerations: 1, + tree_scans: 0, + derivations: 0 + } ); assert_eq!( std::fs::read(&fx.paths.index_path).unwrap(), @@ -912,7 +982,10 @@ mod tests { assert_eq!(engine.stats.stale_reads, 1); assert!(engine.stats.last_error.is_some()); let stats = read_stats_at(&fx.paths.stats_path).expect("stats sidecar"); - assert!(stats.last_error.is_some(), "the failure is an observable fact"); + assert!( + stats.last_error.is_some(), + "the failure is an observable fact" + ); assert!(stats.pending_refresh, "the owed work stays visible"); } @@ -951,8 +1024,14 @@ mod tests { req.endpoints.insert("gone".to_string()); let r = engine.reconcile(&req, false).unwrap(); assert!(r.published); - assert_eq!(r.counters.tree_scans, 0, "unchanged generation: a row patch scans nothing"); - assert_eq!(r.counters.derivations, 0, "proj-a was already in the cwd cache"); + assert_eq!( + r.counters.tree_scans, 0, + "unchanged generation: a row patch scans nothing" + ); + assert_eq!( + r.counters.derivations, 0, + "proj-a was already in the cwd cache" + ); let idx = match projindex::read_index_at(&fx.paths.index_path) { IndexRead::Snapshot(i) => i, @@ -982,7 +1061,10 @@ mod tests { let mut engine = WriterEngine::new(fx.paths.clone()); let r = engine.reconcile(&global(), false).unwrap(); assert!(r.published); - assert_eq!(engine.stats.repairs, 1, "the publish over a torn file is a repair"); + assert_eq!( + engine.stats.repairs, 1, + "the publish over a torn file is a repair" + ); assert!(matches!( projindex::read_index_at(&fx.paths.index_path), IndexRead::Snapshot(_) @@ -1038,7 +1120,10 @@ mod tests { ) .unwrap(); let r3 = engine.reconcile(&global(), true).unwrap(); - assert_eq!(r3.counters.derivations, 1, "a .git/config change re-derives exactly once"); + assert_eq!( + r3.counters.derivations, 1, + "a .git/config change re-derives exactly once" + ); let idx = match projindex::read_index_at(&fx.paths.index_path) { IndexRead::Snapshot(i) => i, other => panic!("{other:?}"), @@ -1059,7 +1144,14 @@ mod tests { let dir_a = fx.project_dir("proj-a"); fx.perch("ep1", None, Some(&dir_a)); let mut engine = WriterEngine::new(fx.paths.clone()); - assert_eq!(engine.reconcile(&global(), false).unwrap().counters.derivations, 1); + assert_eq!( + engine + .reconcile(&global(), false) + .unwrap() + .counters + .derivations, + 1 + ); let mut req = Coalesced::default(); req.endpoints.insert("ep1".to_string()); @@ -1099,7 +1191,10 @@ mod tests { let stats = || read_stats_at(&stats_path()); let deadline = Instant::now() + Duration::from_secs(10); // Wait for the boot cycle to settle. - while stats().map(|s| s.pending_refresh || s.generated_ms == 0).unwrap_or(true) { + while stats() + .map(|s| s.pending_refresh || s.generated_ms == 0) + .unwrap_or(true) + { assert!(Instant::now() < deadline, "boot cycle never settled"); std::thread::sleep(Duration::from_millis(25)); } @@ -1154,8 +1249,14 @@ mod tests { let repo = fx.project_dir("parity-checkout"); spt_store::gitrun::run_git_ok(&["init", &repo.to_string_lossy()], None, None).unwrap(); spt_store::gitrun::run_git_ok( - &["-C", &repo.to_string_lossy(), "remote", "add", "origin", - "git@example.com:Team/Parity.git"], + &[ + "-C", + &repo.to_string_lossy(), + "remote", + "add", + "origin", + "git@example.com:Team/Parity.git", + ], None, None, ) @@ -1202,8 +1303,7 @@ mod tests { .filter_map(|b| { let project = b.strip_prefix("p-")?.to_string(); let rel = format!("{id}/{PROJECT_CONTEXT_FILE}"); - matches!(store.read_at_tip(&b, &rel), Ok(Some(_))) - .then_some(project) + matches!(store.read_at_tip(&b, &rel), Ok(Some(_))).then_some(project) }) .collect() }; @@ -1243,7 +1343,11 @@ mod tests { .collect() }; - assert_eq!(indexed("ep-a"), oracle_a, "ep-a: full ordered history parity"); + assert_eq!( + indexed("ep-a"), + oracle_a, + "ep-a: full ordered history parity" + ); assert_eq!(indexed("ep-b"), oracle_b, "ep-b: branch-only parity"); assert_eq!(indexed("ep-c"), oracle_c, "ep-c: empty parity"); assert!(oracle_c.is_empty()); @@ -1260,12 +1364,14 @@ mod tests { // Per-cwd map parity (the resume pane's source): every ledger/origin // cwd resolves to EXACTLY what the legacy per-row derivation rendered. for cwd in [&repo, &plain, &origin_dir] { - let (want_id, want_display) = - spt_store::project::project_id_and_display_for_dir(cwd); + let (want_id, want_display) = spt_store::project::project_id_and_display_for_dir(cwd); let got = idx .project_for_cwd(cwd) .unwrap_or_else(|| panic!("cwd map must hold {cwd:?}")); - assert_eq!((got.id.as_str(), got.display.as_str()), (want_id.as_str(), want_display.as_str())); + assert_eq!( + (got.id.as_str(), got.display.as_str()), + (want_id.as_str(), want_display.as_str()) + ); } } diff --git a/crates/spt-daemon/src/propagate.rs b/crates/spt-daemon/src/propagate.rs index b4446183..ad5f49d6 100644 --- a/crates/spt-daemon/src/propagate.rs +++ b/crates/spt-daemon/src/propagate.rs @@ -354,7 +354,13 @@ pub fn request_update( let opened = brain.net_open_stream(conn_id, Some(open_op))?; let stream_id = opened.stream_id; let out = request_update_on( - brain, stream_id, open_op, running, policy, cache, scratch_dir, + brain, + stream_id, + open_op, + running, + policy, + cache, + scratch_dir, ); // Requester-side lifetime bound (ADR-0040 decisions 1+5) — the // request_sync twin: release the seat + the physical row when the pull diff --git a/crates/spt-daemon/src/psyrelay.rs b/crates/spt-daemon/src/psyrelay.rs index 605600ce..cce81730 100644 --- a/crates/spt-daemon/src/psyrelay.rs +++ b/crates/spt-daemon/src/psyrelay.rs @@ -347,7 +347,9 @@ mod tests { }] ); assert_eq!(rows[0].from, "doyle-psyche"); - assert!(!rows[0].from.contains("evil-imposter") && !rows[0].body.contains("evil-imposter")); + assert!( + !rows[0].from.contains("evil-imposter") && !rows[0].body.contains("evil-imposter") + ); // The Psyche-addressed target received nothing. assert!(spool::drain_all_at(&victim).unwrap().is_empty()); }); diff --git a/crates/spt-daemon/src/pump/health.rs b/crates/spt-daemon/src/pump/health.rs index 47b8642f..76b19ab2 100644 --- a/crates/spt-daemon/src/pump/health.rs +++ b/crates/spt-daemon/src/pump/health.rs @@ -407,8 +407,8 @@ impl PumpHealth { } else { self.all_fail_since_ms = None; } - let any_failing = !self.targets.is_empty() - && self.targets.iter().any(|t| self.failing.contains_key(t)); + let any_failing = + !self.targets.is_empty() && self.targets.iter().any(|t| self.failing.contains_key(t)); if any_failing { self.any_fail_since_ms.get_or_insert(now_ms); } else { @@ -510,7 +510,8 @@ impl PumpHealth { if self.failing.is_empty() { return false; } - let (Some(sampled), Some(admitted)) = (self.node_offline_at_ms, self.last_registry_admit_ms) + let (Some(sampled), Some(admitted)) = + (self.node_offline_at_ms, self.last_registry_admit_ms) else { return false; // never sampled, or never admitted a feed: no basis }; @@ -548,7 +549,10 @@ mod tests { parse_stage("stage=quic-connect: submit-dial exceeded the 10s bound"), "quic-connect" ); - assert_eq!(parse_stage("stage=seed-proof-recv: peer is not a member"), "seed-proof-recv"); + assert_eq!( + parse_stage("stage=seed-proof-recv: peer is not a member"), + "seed-proof-recv" + ); assert_eq!(parse_stage("stage=alpn: connection refused"), "alpn"); assert_eq!(parse_stage("dial failed"), "unknown"); } @@ -565,7 +569,10 @@ mod tests { h.set_targets(["a".to_string(), "b".to_string()], 1_000); assert_eq!(h.verdict(), HealthVerdict::Connecting, "nothing failed yet"); - assert!(h.note_failed("a", "quic-connect", NONE, 2_000), "new failure logs"); + assert!( + h.note_failed("a", "quic-connect", NONE, 2_000), + "new failure logs" + ); // UNCHANGED by #41, and deliberately so: one of two failing with // NOTHING live is still the connecting state, not a partial outage — // `DegradedPartial` claims some peers are reachable, and none are here. @@ -574,22 +581,43 @@ mod tests { HealthVerdict::Connecting, "one of two failing: not yet the fingerprint" ); - assert_eq!(h.all_fail_since_ms, None, "the sequester window is NOT open on one failure"); + assert_eq!( + h.all_fail_since_ms, None, + "the sequester window is NOT open on one failure" + ); assert!(h.note_failed("b", "quic-connect", NONE, 3_000)); match h.verdict() { - HealthVerdict::Degraded { failing, total, stage, since_ms } => { + HealthVerdict::Degraded { + failing, + total, + stage, + since_ms, + } => { assert_eq!((failing, total), (2, 2)); assert_eq!(stage, "quic-connect", "the verdict names the stage"); - assert_eq!(since_ms, Some(3_000), "the window opened at the closing failure"); + assert_eq!( + since_ms, + Some(3_000), + "the window opened at the closing failure" + ); } v => panic!("expected degraded, got {v:?}"), } // Repeated same-stage failures: still degraded, window start UNCHANGED // (duration accumulates), and the repeat is not transition-newsy. - assert!(!h.note_failed("a", "quic-connect", NONE, 9_000), "same stage: quiet repeat"); - assert!(matches!(h.verdict(), HealthVerdict::Degraded { since_ms: Some(3_000), .. })); + assert!( + !h.note_failed("a", "quic-connect", NONE, 9_000), + "same stage: quiet repeat" + ); + assert!(matches!( + h.verdict(), + HealthVerdict::Degraded { + since_ms: Some(3_000), + .. + } + )); // A stage CHANGE is newsy (the operator learns where it dies now). assert!(h.note_failed("a", "seed-proof-recv", NONE, 10_000)); @@ -601,12 +629,28 @@ mod tests { // original assertion ("healthy only on real progress") is preserved // and sharpened below: green needs progress on EVERY target. h.note_connected("a", ["a"], 11_000); - assert_eq!(h.all_fail_since_ms, None, "real progress closed the all-fail window"); + assert_eq!( + h.all_fail_since_ms, None, + "real progress closed the all-fail window" + ); assert_eq!(h.last_dial_ok_ms, Some(11_000)); match h.verdict() { - HealthVerdict::DegradedPartial { failing, total, since_ms, .. } => { - assert_eq!((failing, total), (1, 2), "b is still failing behind the live peer"); - assert_eq!(since_ms, Some(2_000), "the incident clock runs from the FIRST failure"); + HealthVerdict::DegradedPartial { + failing, + total, + since_ms, + .. + } => { + assert_eq!( + (failing, total), + (1, 2), + "b is still failing behind the live peer" + ); + assert_eq!( + since_ms, + Some(2_000), + "the incident clock runs from the FIRST failure" + ); } v => panic!("expected degraded-partial, got {v:?}"), } @@ -614,7 +658,10 @@ mod tests { // Green only when nothing is failing any more. h.note_connected("b", ["a", "b"], 12_000); assert_eq!(h.verdict(), HealthVerdict::Healthy); - assert_eq!(h.any_fail_since_ms, None, "the last failure cleared closed the any-fail window"); + assert_eq!( + h.any_fail_since_ms, None, + "the last failure cleared closed the any-fail window" + ); // No targets = idle, never degraded. let mut solo = PumpHealth::default(); @@ -662,10 +709,23 @@ mod tests { // shape: the fault this surface exists to report is persistent per-peer // dial failure, and no amount of it may produce the surface's green. // Five peers failing for the whole run is that fault at full strength. - assert_ne!(v, HealthVerdict::Healthy, "the 2-of-7-live outage must never read green: {v:?}"); + assert_ne!( + v, + HealthVerdict::Healthy, + "the 2-of-7-live outage must never read green: {v:?}" + ); match v { - HealthVerdict::DegradedPartial { failing, total, stage, since_ms } => { - assert_eq!((failing, total), (5, 7), "names how many of how many are unreachable"); + HealthVerdict::DegradedPartial { + failing, + total, + stage, + since_ms, + } => { + assert_eq!( + (failing, total), + (5, 7), + "names how many of how many are unreachable" + ); assert_eq!(stage, "quic-connect", "and the layer they die at"); assert_eq!( since_ms, @@ -678,7 +738,10 @@ mod tests { // It is NOT the full-sequester fingerprint either — two peers really // are reachable, and the operator must not be told otherwise. - assert_eq!(h.all_fail_since_ms, None, "not a sequester: live peers exist"); + assert_eq!( + h.all_fail_since_ms, None, + "not a sequester: live peers exist" + ); assert_eq!(h.live_peers, 2, "the live count is still reported honestly"); } @@ -697,8 +760,15 @@ mod tests { h.note_failed("a", "quic-connect", NONE, 2_000); // ← the incident starts here h.note_failed("b", "quic-connect", NONE, 3_000); - assert_eq!(h.any_fail_since_ms, Some(2_000), "the any-fail window opened at the first failure"); - assert_eq!(h.all_fail_since_ms, None, "c has not failed: not yet a sequester"); + assert_eq!( + h.any_fail_since_ms, + Some(2_000), + "the any-fail window opened at the first failure" + ); + assert_eq!( + h.all_fail_since_ms, None, + "c has not failed: not yet a sequester" + ); // Escalation to the total-failure fingerprint. UNCHANGED BY #41: the // full verdict, its count, its stage, and its OWN window (which starts @@ -714,15 +784,27 @@ mod tests { }, "the total-failure fingerprint still renders the full verdict, on its own window" ); - assert_eq!(h.any_fail_since_ms, Some(2_000), "the any-fail window spans the sequester"); + assert_eq!( + h.any_fail_since_ms, + Some(2_000), + "the any-fail window spans the sequester" + ); // ONE peer comes back, much later. This is real progress and it closes // the sequester — but it is not recovery, and it must not erase how old // the incident is. h.note_connected("a", ["a"], 900_000); - assert_eq!(h.all_fail_since_ms, None, "real progress closed the sequester window"); + assert_eq!( + h.all_fail_since_ms, None, + "real progress closed the sequester window" + ); match h.verdict() { - HealthVerdict::DegradedPartial { failing, total, since_ms, .. } => { + HealthVerdict::DegradedPartial { + failing, + total, + since_ms, + .. + } => { assert_eq!((failing, total), (2, 3), "narrowed, not cleared"); assert_eq!( since_ms, @@ -736,21 +818,45 @@ mod tests { // A second peer returning narrows it again — and STILL does not close // the window, because c is still failing. h.note_connected("b", ["a", "b"], 950_000); - assert_eq!(h.any_fail_since_ms, Some(2_000), "the window closes only when the failing set empties"); - assert!(matches!( - h.verdict(), - HealthVerdict::DegradedPartial { failing: 1, total: 3, since_ms: Some(2_000), .. } - ), "got {:?}", h.verdict()); + assert_eq!( + h.any_fail_since_ms, + Some(2_000), + "the window closes only when the failing set empties" + ); + assert!( + matches!( + h.verdict(), + HealthVerdict::DegradedPartial { + failing: 1, + total: 3, + since_ms: Some(2_000), + .. + } + ), + "got {:?}", + h.verdict() + ); // The last failing peer returning is what closes it. h.note_connected("c", ["a", "b", "c"], 960_000); - assert_eq!(h.any_fail_since_ms, None, "an empty failing set closes the any-fail window"); - assert_eq!(h.verdict(), HealthVerdict::Healthy, "green needs progress on EVERY target"); + assert_eq!( + h.any_fail_since_ms, None, + "an empty failing set closes the any-fail window" + ); + assert_eq!( + h.verdict(), + HealthVerdict::Healthy, + "green needs progress on EVERY target" + ); // And a FRESH failure after the close opens a NEW incident, rather than // resurrecting the old start (the window is not sticky). h.note_failed("c", "alpn", ["a", "b"], 1_000_000); - assert_eq!(h.any_fail_since_ms, Some(1_000_000), "a new incident is measured from its own start"); + assert_eq!( + h.any_fail_since_ms, + Some(1_000_000), + "a new incident is measured from its own start" + ); } // [unit->REQ-PEER-HEALTH-PARTIAL-DEGRADE] the roster-churn edge: a peer @@ -766,22 +872,48 @@ mod tests { h.set_targets(["a".to_string(), "b".to_string()], 1_000); h.note_connected("a", ["a"], 1_500); h.note_failed("b", "quic-connect", ["a"], 2_000); - assert!(matches!(h.verdict(), HealthVerdict::DegradedPartial { failing: 1, total: 2, .. })); + assert!(matches!( + h.verdict(), + HealthVerdict::DegradedPartial { + failing: 1, + total: 2, + .. + } + )); // b leaves the roster: the next round's targets no longer include it. h.set_targets(["a".to_string()], 3_000); - assert!(!h.failing.contains_key("b"), "a departed peer drops out of the failing set"); - assert_eq!(h.any_fail_since_ms, None, "and with it, the incident window"); - assert_eq!(h.verdict(), HealthVerdict::Healthy, "nothing is failing among the peers we have"); + assert!( + !h.failing.contains_key("b"), + "a departed peer drops out of the failing set" + ); + assert_eq!( + h.any_fail_since_ms, None, + "and with it, the incident window" + ); + assert_eq!( + h.verdict(), + HealthVerdict::Healthy, + "nothing is failing among the peers we have" + ); // The control: a target that stays IS still held against us. h.set_targets(["a".to_string(), "b".to_string()], 4_000); h.note_failed("b", "quic-connect", ["a"], 5_000); h.set_targets(["a".to_string(), "b".to_string()], 6_000); - assert!(matches!( - h.verdict(), - HealthVerdict::DegradedPartial { failing: 1, total: 2, since_ms: Some(5_000), .. } - ), "a re-listed target keeps its failure across rounds: {:?}", h.verdict()); + assert!( + matches!( + h.verdict(), + HealthVerdict::DegradedPartial { + failing: 1, + total: 2, + since_ms: Some(5_000), + .. + } + ), + "a re-listed target keeps its failure across rounds: {:?}", + h.verdict() + ); } // [unit->REQ-PEER-COUNT-TARGET-SCOPED] THE FIELD SPECIMEN, exactly as it @@ -836,15 +968,25 @@ mod tests { let mut h = PumpHealth::default(); h.set_targets(["a".to_string()], 1_000); h.note_connected("bystander", ["bystander"], 2_000); - assert_eq!(h.live_peers, 0, "a live non-target is not one of the peers we are reaching"); - assert_eq!(h.verdict(), HealthVerdict::Connecting, "and it cannot render us green"); + assert_eq!( + h.live_peers, 0, + "a live non-target is not one of the peers we are reaching" + ); + assert_eq!( + h.verdict(), + HealthVerdict::Connecting, + "and it cannot render us green" + ); h.note_connected("a", ["bystander", "a"], 3_000); assert_eq!(h.live_peers, 1, "only the target counts"); assert_eq!(h.verdict(), HealthVerdict::Healthy); h.note_disconnected(["bystander"]); - assert_eq!(h.live_peers, 0, "the target's connection went away with the mirror"); + assert_eq!( + h.live_peers, 0, + "the target's connection went away with the mirror" + ); assert_eq!(h.connected, BTreeSet::from(["bystander".to_string()])); } @@ -871,8 +1013,17 @@ mod tests { h.note_node_absence(["a"], 1_000_200); match h.verdict() { - HealthVerdict::PeersAbsent { absent, total, stage, since_ms } => { - assert_eq!((absent, total), (1, 1), "names how many of how many are absent"); + HealthVerdict::PeersAbsent { + absent, + total, + stage, + since_ms, + } => { + assert_eq!( + (absent, total), + (1, 1), + "names how many of how many are absent" + ); assert_eq!(stage, "quic-connect", "and the layer their dials die at"); assert_eq!( since_ms, @@ -882,7 +1033,11 @@ mod tests { } v => panic!("expected peers-absent, got {v:?}"), } - assert_ne!(h.verdict(), HealthVerdict::Healthy, "absent is never a synonym for healthy"); + assert_ne!( + h.verdict(), + HealthVerdict::Healthy, + "absent is never a synonym for healthy" + ); } // [unit->REQ-PEER-ABSENCE-VERDICT] THE #41 FIELD SHAPE IS UNCHANGED unless @@ -905,7 +1060,14 @@ mod tests { h.note_node_absence(["p3", "p4", "p5", "p6"], 1_000_200); assert!( - matches!(h.verdict(), HealthVerdict::DegradedPartial { failing: 5, total: 7, .. }), + matches!( + h.verdict(), + HealthVerdict::DegradedPartial { + failing: 5, + total: 7, + .. + } + ), "four of five accounted for is not all of them: {:?}", h.verdict() ); @@ -913,7 +1075,14 @@ mod tests { // The fifth, and only the fifth, flips it. h.note_node_absence(["p3", "p4", "p5", "p6", "p7"], 1_000_300); assert!( - matches!(h.verdict(), HealthVerdict::PeersAbsent { absent: 5, total: 7, .. }), + matches!( + h.verdict(), + HealthVerdict::PeersAbsent { + absent: 5, + total: 7, + .. + } + ), "every failing peer independently accounted for: {:?}", h.verdict() ); @@ -948,7 +1117,14 @@ mod tests { // Sampled exactly at the edge of the window: still an observation. h.note_node_absence(["a", "b"], 1_000_000 + ADMIT_FRESH_MS); assert!( - matches!(h.verdict(), HealthVerdict::PeersAbsent { absent: 2, total: 2, .. }), + matches!( + h.verdict(), + HealthVerdict::PeersAbsent { + absent: 2, + total: 2, + .. + } + ), "at the boundary the evidence still counts: {:?}", h.verdict() ); @@ -956,7 +1132,14 @@ mod tests { // One millisecond past it: memory, not observation. h.note_node_absence(["a", "b"], 1_000_001 + ADMIT_FRESH_MS); assert!( - matches!(h.verdict(), HealthVerdict::Degraded { failing: 2, total: 2, .. }), + matches!( + h.verdict(), + HealthVerdict::Degraded { + failing: 2, + total: 2, + .. + } + ), "stale gossip cannot vouch for anyone's absence: {:?}", h.verdict() ); @@ -1003,14 +1186,25 @@ mod tests { // applies. h.note_connected("b", ["b"], 1_000_300); assert!( - matches!(h.verdict(), HealthVerdict::PeersAbsent { absent: 1, total: 2, .. }), + matches!( + h.verdict(), + HealthVerdict::PeersAbsent { + absent: 1, + total: 2, + .. + } + ), "{:?}", h.verdict() ); // Nothing failing: unreachable, whatever the registry says. h.note_connected("a", ["a", "b"], 1_000_400); - assert_eq!(h.verdict(), HealthVerdict::Healthy, "an empty failing set is green, not absent"); + assert_eq!( + h.verdict(), + HealthVerdict::Healthy, + "an empty failing set is green, not absent" + ); // The roster-churn edge: a departed target's offline evidence departs // with it, so a stale claim about a peer we no longer reach can never @@ -1019,8 +1213,15 @@ mod tests { h.note_node_absence(["a"], 1_000_600); assert!(matches!(h.verdict(), HealthVerdict::PeersAbsent { .. })); h.set_targets(["b".to_string()], 1_000_700); - assert!(h.node_offline.is_empty(), "the departed target's evidence departed with it"); - assert_eq!(h.verdict(), HealthVerdict::Healthy, "nothing is failing among the peers we have"); + assert!( + h.node_offline.is_empty(), + "the departed target's evidence departed with it" + ); + assert_eq!( + h.verdict(), + HealthVerdict::Healthy, + "nothing is failing among the peers we have" + ); } // [unit->REQ-PUMP-STAGE-TRUTH] the restart shape (gate round 1): the @@ -1046,7 +1247,11 @@ mod tests { for _ in 0..3 { h.note_registry_admit(None); } - assert_eq!(h.last_registry_admit_ms, Some(1_000), "None keeps the last-good stamp"); + assert_eq!( + h.last_registry_admit_ms, + Some(1_000), + "None keeps the last-good stamp" + ); h.save_to(&path); assert_eq!( PumpHealth::load_from(&path).last_registry_admit_ms, @@ -1056,9 +1261,17 @@ mod tests { // A real new admit advances it; an older stamp never regresses it. h.note_registry_admit(Some(2_000)); - assert_eq!(h.last_registry_admit_ms, Some(2_000), "a fresh admit advances"); + assert_eq!( + h.last_registry_admit_ms, + Some(2_000), + "a fresh admit advances" + ); h.note_registry_admit(Some(500)); - assert_eq!(h.last_registry_admit_ms, Some(2_000), "an older stamp never regresses"); + assert_eq!( + h.last_registry_admit_ms, + Some(2_000), + "an older stamp never regresses" + ); } // [unit->REQ-PUMP-STAGE-TRUTH] the snapshot round-trips through disk and @@ -1067,7 +1280,11 @@ mod tests { fn health_file_roundtrip_and_degrade() { let dir = tempfile::tempdir().unwrap(); let path = dir.path().join("pump-health.json"); - assert_eq!(PumpHealth::load_from(&path), PumpHealth::default(), "absent = default"); + assert_eq!( + PumpHealth::load_from(&path), + PumpHealth::default(), + "absent = default" + ); let mut h = PumpHealth::default(); h.set_targets(["a".to_string()], 1); @@ -1077,6 +1294,10 @@ mod tests { assert_eq!(PumpHealth::load_from(&path), h, "roundtrip"); std::fs::write(&path, "garbage{{{").unwrap(); - assert_eq!(PumpHealth::load_from(&path), PumpHealth::default(), "corrupt = default"); + assert_eq!( + PumpHealth::load_from(&path), + PumpHealth::default(), + "corrupt = default" + ); } } diff --git a/crates/spt-daemon/src/pump/mod.rs b/crates/spt-daemon/src/pump/mod.rs index 509ae7f2..130b4504 100644 --- a/crates/spt-daemon/src/pump/mod.rs +++ b/crates/spt-daemon/src/pump/mod.rs @@ -75,7 +75,7 @@ use spt_store::visibility::VisibilityStore; use crate::brain::{Brain, BrokerEvent, PEER_REPLY_READ_BUDGET}; use crate::config::DaemonConfig; -use crate::effect::{Minter, MintedOp}; +use crate::effect::{MintedOp, Minter}; use crate::msg::{ NetPresenceEvent, PRESENCE_CONNECTED, PRESENCE_DIAL_FAILED, PRESENCE_DISCONNECTED, }; @@ -90,16 +90,16 @@ mod registry; mod seal; mod sync; mod update; +use notif::NotifWorker; +use registry::RegistryWorker; +use seal::SealWorker; +use sync::SyncWorker; /// The update-staged notif catch-up dismissal seam (ADR-0046 decision 3) — /// exposed for the seam-dismissal integration test. pub use update::dismiss_staged_notif_if_caught_up; /// The version-grounded retirement sweep for KEYLESS legacy update rows (W2 /// rider) — the sibling of the key path above, exposed for its rig. pub use update::retire_update_rows_the_running_image_has_passed; -use notif::NotifWorker; -use registry::RegistryWorker; -use seal::SealWorker; -use sync::SyncWorker; use update::UpdateWorker; /// The pump's tick granularity — each cadence fires when its period elapsed. @@ -644,9 +644,13 @@ pub fn run_peer_pump( let mut seal_worker = SealWorker::new(paths, &cadence); // #41: the pull hook goes to the sync worker; the dial-path hook stays // here, on the loop that submits dials. - let PumpHooks { on_pull, mut on_dial_submit } = hooks; + let PumpHooks { + on_pull, + mut on_dial_submit, + } = hooks; let mut sync_worker = SyncWorker::new(Arc::clone(®istry), paths, &cadence, on_pull); - let mut update_worker = UpdateWorker::new(Arc::clone(®istry), paths, &cadence, full_auto_update); + let mut update_worker = + UpdateWorker::new(Arc::clone(®istry), paths, &cadence, full_auto_update); let mut workers: [&mut dyn PumpWorker; 5] = [ &mut registry_worker, &mut notif_worker, @@ -740,8 +744,17 @@ pub fn run_peer_pump( for (peer_hex, subs) in &peer_subnets { if let Some(&conn_id) = conns.get(peer_hex) { run_peer_subnets( - &mut brain, &mut ops, &mut workers, &due_flags, &mut conns, &mut sched, - conn_id, subs, peer_hex, &ctx, round_start, + &mut brain, + &mut ops, + &mut workers, + &due_flags, + &mut conns, + &mut sched, + conn_id, + subs, + peer_hex, + &ctx, + round_start, )?; } else if peer_eligible(&sched, peer_hex, round_start) { let (route, leg) = resolve_submit_addr( @@ -828,9 +841,20 @@ pub fn run_peer_pump( }; match classify_drain_read(events.read_event_until(Some(read_deadline))) { DrainStep::Apply(ev) => handle_presence_event( - ev, &mut brain, &mut ops, &mut workers, &due_flags, &mut conns, &mut sched, - &mut pending, &peer_subnets, &ctx, &paths.peer_addrs, &mut health, - &dialed_legs, round_start, + ev, + &mut brain, + &mut ops, + &mut workers, + &due_flags, + &mut conns, + &mut sched, + &mut pending, + &peer_subnets, + &ctx, + &paths.peer_addrs, + &mut health, + &dialed_legs, + round_start, )?, DrainStep::Skip => continue, // the event carrier only carries presence DrainStep::RoundDone => break, // quiet (TimedOut) — drain done @@ -991,7 +1015,15 @@ fn handle_presence_event( ) -> io::Result<()> { let is_target = peer_subnets.contains_key(&ev.remote_id_hex); if presence_state_effect( - &ev, conns, sched, pending, peer_addrs, health, dialed_legs, is_target, now, + &ev, + conns, + sched, + pending, + peer_addrs, + health, + dialed_legs, + is_target, + now, ) { // A CONNECTED peer that is a fan target this round → advertise NOW. if let Some(subs) = peer_subnets.get(&ev.remote_id_hex) { @@ -1240,8 +1272,8 @@ fn resolve_submit_addr( Some(rostered) if !failed.is_failed(&rostered) => { return (Some(rostered), RouteLeg::Roster); } - Some(_) => true, // a roster address exists and was deliberately refused - None => false, // no roster address at all + Some(_) => true, // a roster address exists and was deliberately refused + None => false, // no roster address at all }; match (resolver(peer_hex), skipped) { (Some(addr), true) => (Some(addr), RouteLeg::DiscoveryAfterRosterSkip), @@ -1373,14 +1405,11 @@ fn readvertise_if_rebound( ctx: &RoundCtx, ) { let self_hex = registry.node_hex(); - let Ok(status) = brain.net_status() else { return }; + let Ok(status) = brain.net_status() else { + return; + }; let live = status.addr; - let subnets: Vec = ctx - .subnets - .subnets - .iter() - .map(|s| s.name.clone()) - .collect(); + let subnets: Vec = ctx.subnets.subnets.iter().map(|s| s.name.clone()).collect(); let roster_path = node_roster_path(paths); let mut roster = spt_store::roster::RosterStore::load_from(&roster_path); // The lease has to clear the fleet's ceiling or the re-authored rows merge @@ -1392,7 +1421,14 @@ fn readvertise_if_rebound( let machine_id = crate::machineid::machine_id_hash().unwrap_or_default(); let now = (now_ms() / 1000).to_string(); if !refresh_self_addr( - &mut roster, self_hex, &live, &subnets, &label, &machine_id, &now, lease, + &mut roster, + self_hex, + &live, + &subnets, + &label, + &machine_id, + &now, + lease, ) { return; } @@ -1470,9 +1506,8 @@ fn startup_heal_self_lease(paths: &PumpPaths, registry: &RegistryHost) { // The node's CANONICAL counter, borrowed from the registry host that owns it // — never `ops` (a separate counter file, the notif-id collision trap) and // never a freshly loaded source (issue #48 rider: the heal is a writer). - let _ = registry.with_epoch(|ep| { - crate::seedproofx::heal_self_lease(&roster, registry.node_hex(), ep) - }); + let _ = registry + .with_epoch(|ep| crate::seedproofx::heal_self_lease(&roster, registry.node_hex(), ep)); } /// Startup reconcile + invariant migration over `peer-addrs.json` (ADR-0039 @@ -1658,7 +1693,9 @@ pub fn supervise_pump(stop: &AtomicBool, base: Duration, mut body: impl FnMut() match outcome { // The body only returns Ok when stop is raised; reaching here // without it is a died-loop fact — same restart as an error. - Ok(Ok(())) => spt_proto::emit_line_err!("PEER_PUMP_EXIT: loop returned without stop — restarting"), + Ok(Ok(())) => { + spt_proto::emit_line_err!("PEER_PUMP_EXIT: loop returned without stop — restarting") + } Ok(Err(e)) => spt_proto::emit_line_err!("PEER_PUMP_FAIL: {e}"), Err(panic) => { let msg = panic @@ -1834,7 +1871,12 @@ mod tests { } } - fn rec(cadence: Duration, wake: bool, log: &Rc>>, tag: char) -> RecordingWorker { + fn rec( + cadence: Duration, + wake: bool, + log: &Rc>>, + tag: char, + ) -> RecordingWorker { RecordingWorker { cadence, wake, @@ -1903,7 +1945,10 @@ mod tests { // pre_round once each for the two due workers, never for the not-due one. assert_eq!(l.iter().filter(|e| e.as_str() == "pre:a").count(), 1); assert_eq!(l.iter().filter(|e| e.as_str() == "pre:c").count(), 1); - assert!(!l.iter().any(|e| e == "pre:b"), "not-due leg never pre_rounds"); + assert!( + !l.iter().any(|e| e == "pre:b"), + "not-due leg never pre_rounds" + ); // All pre_rounds precede all peer_steps. let first_step = l.iter().position(|e| e.starts_with("step:")).unwrap(); assert!( @@ -1912,7 +1957,11 @@ mod tests { ); // peer_step runs for due indices only (0 and 2), once per peer (×2). assert_eq!(l.iter().filter(|e| e.as_str() == "step:0").count(), 2); - assert_eq!(l.iter().filter(|e| e.as_str() == "step:1").count(), 0, "not-due skipped"); + assert_eq!( + l.iter().filter(|e| e.as_str() == "step:1").count(), + 0, + "not-due skipped" + ); assert_eq!(l.iter().filter(|e| e.as_str() == "step:2").count(), 2); } @@ -1931,7 +1980,10 @@ mod tests { Ok(()) } }); - assert!(res.is_err(), "the failure propagates so the shell drops the conn"); + assert!( + res.is_err(), + "the failure propagates so the shell drops the conn" + ); assert_eq!(seen, vec![0, 1], "aborted before the remaining due worker"); // Skip: a not-due index is never stepped. @@ -2003,8 +2055,12 @@ mod tests { lease_epoch: 1, }; let mut subnets = SubnetStore::default(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); - subnets.create_subnet("work", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); + subnets + .create_subnet("work", spt_store::access::Mode::Open) + .unwrap(); let mut roster = RosterStore::default(); roster.merge_entry(entry("home", "self")); roster.merge_entry(entry("home", "aa")); @@ -2052,7 +2108,10 @@ mod tests { // Ordinary error → conn dropped + peer backed off, round continues (Ok). let ordinary = io::Error::other("peer refused the stream"); assert!(peer_leg_outcome(Err(ordinary), "bb", &mut conns, &mut sched, now).is_ok()); - assert!(!conns.contains_key("bb"), "an ordinary failure drops the conn"); + assert!( + !conns.contains_key("bb"), + "an ordinary failure drops the conn" + ); assert!( !peer_eligible(&sched, "bb", now), "and backs the peer off (not eligible until next_due)" @@ -2065,12 +2124,18 @@ mod tests { "peer never answered the Query", )); assert!(peer_leg_outcome(Err(silent), "aa", &mut conns, &mut sched, now).is_ok()); - assert!(!conns.contains_key("aa"), "a silent peer drops without a round abort"); + assert!( + !conns.contains_key("aa"), + "a silent peer drops without a round abort" + ); // A genuine carrier-op raw TimedOut STILL poisons → supervised restart. let carrier = io::Error::new(io::ErrorKind::TimedOut, "brain IPC carrier desync"); let bubbled = peer_leg_outcome(Err(carrier), "cc", &mut conns, &mut sched, now); - assert!(bubbled.is_err(), "a real carrier desync still restarts the pump"); + assert!( + bubbled.is_err(), + "a real carrier desync still restarts the pump" + ); assert_eq!(bubbled.unwrap_err().kind(), io::ErrorKind::TimedOut); } @@ -2099,11 +2164,21 @@ mod tests { // Eligibility: no entry = eligible; in-backoff = not until next_due passes. let mut sched: HashMap = HashMap::new(); - assert!(peer_eligible(&sched, "fresh", now), "never-failed peer is eligible"); + assert!( + peer_eligible(&sched, "fresh", now), + "never-failed peer is eligible" + ); sched.insert("dead".into(), next_peer_backoff(None, now)); - assert!(!peer_eligible(&sched, "dead", now), "in backoff → not eligible"); assert!( - peer_eligible(&sched, "dead", now + PEER_BACKOFF_BASE + Duration::from_millis(1)), + !peer_eligible(&sched, "dead", now), + "in backoff → not eligible" + ); + assert!( + peer_eligible( + &sched, + "dead", + now + PEER_BACKOFF_BASE + Duration::from_millis(1) + ), "eligible again once next_due elapses" ); } @@ -2124,8 +2199,9 @@ mod tests { let legs: HashMap = HashMap::new(); let mut conns: HashMap = HashMap::new(); let mut sched: HashMap = HashMap::new(); - let mut pending: HashSet = - ["live".to_string(), "dead".to_string()].into_iter().collect(); + let mut pending: HashSet = ["live".to_string(), "dead".to_string()] + .into_iter() + .collect(); let mut health = PumpHealth::default(); let ev = |kind: &str, conn_id: u64, hex: &str| NetPresenceEvent { @@ -2140,43 +2216,90 @@ mod tests { // DIAL_FAILED for "dead" → back off, clear pending, no conn, no legs. assert!(!presence_state_effect( &ev(PRESENCE_DIAL_FAILED, 0, "dead"), - &mut conns, &mut sched, &mut pending, &seeds, &mut health, &legs, false, now, + &mut conns, + &mut sched, + &mut pending, + &seeds, + &mut health, + &legs, + false, + now, )); assert!(!peer_eligible(&sched, "dead", now), "dead peer backed off"); assert!(!pending.contains("dead"), "its pending flag cleared"); assert!(!conns.contains_key("dead")); // CONNECTED for "live" that IS a target → cache conn, reset, run legs. - assert!(presence_state_effect( - &ev(PRESENCE_CONNECTED, 9, "live"), - &mut conns, &mut sched, &mut pending, &seeds, &mut health, &legs, true, now, - ), "a connected fan-target signals legs-to-run"); + assert!( + presence_state_effect( + &ev(PRESENCE_CONNECTED, 9, "live"), + &mut conns, + &mut sched, + &mut pending, + &seeds, + &mut health, + &legs, + true, + now, + ), + "a connected fan-target signals legs-to-run" + ); assert_eq!(conns.get("live"), Some(&9), "conn cached under its hex"); assert!(!sched.contains_key("live"), "backoff reset on connect"); assert!(!pending.contains("live")); // CONNECTED for a peer that is NOT a target → cache but DON'T run legs. - assert!(!presence_state_effect( - &ev(PRESENCE_CONNECTED, 5, "bystander"), - &mut conns, &mut sched, &mut pending, &seeds, &mut health, &legs, false, now, - ), "a non-target connect caches without running legs"); + assert!( + !presence_state_effect( + &ev(PRESENCE_CONNECTED, 5, "bystander"), + &mut conns, + &mut sched, + &mut pending, + &seeds, + &mut health, + &legs, + false, + now, + ), + "a non-target connect caches without running legs" + ); assert_eq!(conns.get("bystander"), Some(&5)); // A stale-backoff peer that CONNECTS is immediately hot again (reset). sched.insert("returner".into(), next_peer_backoff(None, now)); presence_state_effect( &ev(PRESENCE_CONNECTED, 7, "returner"), - &mut conns, &mut sched, &mut pending, &seeds, &mut health, &legs, false, now, + &mut conns, + &mut sched, + &mut pending, + &seeds, + &mut health, + &legs, + false, + now, + ); + assert!( + peer_eligible(&sched, "returner", now), + "a returning peer re-dials promptly" ); - assert!(peer_eligible(&sched, "returner", now), "a returning peer re-dials promptly"); // DISCONNECTED for conn 9 → drop "live"'s conn, NO backoff (redial-eligible). presence_state_effect( &ev(PRESENCE_DISCONNECTED, 9, "live"), - &mut conns, &mut sched, &mut pending, &seeds, &mut health, &legs, false, now, + &mut conns, + &mut sched, + &mut pending, + &seeds, + &mut health, + &legs, + false, + now, ); assert!(!conns.contains_key("live"), "disconnected conn dropped"); - assert!(peer_eligible(&sched, "live", now), "disconnect → no backoff (Q3)"); + assert!( + peer_eligible(&sched, "live", now), + "disconnect → no backoff (Q3)" + ); } // [unit->REQ-HAZARD-PUMP-IPC-DEADLINE] [unit->REQ-PUMP-PEER-ISOLATION] the @@ -2192,7 +2315,10 @@ mod tests { fn drain_read_classifies_dead_carrier_as_restart_timeout_as_quiet() { // A quiet TimedOut closes the round — it is NEVER a restart. assert!(matches!( - classify_drain_read(Err(io::Error::new(io::ErrorKind::TimedOut, "read deadline"))), + classify_drain_read(Err(io::Error::new( + io::ErrorKind::TimedOut, + "read deadline" + ))), DrainStep::RoundDone )); // A dead broker mid-drain: the reader thread ended → UnexpectedEof (or a @@ -2205,7 +2331,10 @@ mod tests { DrainStep::Restart(_) )); assert!(matches!( - classify_drain_read(Err(io::Error::new(io::ErrorKind::BrokenPipe, "broker gone"))), + classify_drain_read(Err(io::Error::new( + io::ErrorKind::BrokenPipe, + "broker gone" + ))), DrainStep::Restart(_) )); // A presence event applies; any other frame kind is skipped. @@ -2486,15 +2615,17 @@ mod tests { failed.note_failed("ab", &dead); let mut holds_the_dead_addr = spt_store::roster::RosterStore::default(); - holds_the_dead_addr.members.push(spt_store::roster::RosterEntry { - pubkey_hex: "ab".into(), - subnet: "home".into(), - label: "lbl".into(), - machine_id: "mid".into(), - address: Some(dead.clone()), - last_seen: "1700000000".into(), - lease_epoch: 1, - }); + holds_the_dead_addr + .members + .push(spt_store::roster::RosterEntry { + pubkey_hex: "ab".into(), + subnet: "home".into(), + label: "lbl".into(), + machine_id: "mid".into(), + address: Some(dead.clone()), + last_seen: "1700000000".into(), + lease_epoch: 1, + }); let empty_roster = spt_store::roster::RosterStore::default(); // Route-less DESPITE holding a roster address — the node refused its @@ -2574,7 +2705,11 @@ mod tests { ); // The Display used at the submit/refused log sites and the token // matched by the tests are ONE string, never two literals. - assert_eq!(leg.to_string(), leg.token(), "{leg:?} renders its own token"); + assert_eq!( + leg.to_string(), + leg.token(), + "{leg:?} renders its own token" + ); } // PREFIX-FREE, and this is the assertion that makes the whole split @@ -2618,7 +2753,11 @@ mod tests { !refresh_self_addr(&mut roster, "me", &old, &subs, "lbl", "mid", "2", 9), "an unchanged address rewrites nothing" ); - assert_eq!(roster.find("home", "me").unwrap().lease_epoch, 5, "no epoch burned"); + assert_eq!( + roster.find("home", "me").unwrap().lease_epoch, + 5, + "no epoch burned" + ); assert!( !refresh_self_addr( @@ -2633,7 +2772,10 @@ mod tests { ), "a null (net-less) address is never advertised" ); - assert_eq!(roster.find("home", "me").unwrap().address, Some(old.clone())); + assert_eq!( + roster.find("home", "me").unwrap().address, + Some(old.clone()) + ); assert!( refresh_self_addr(&mut roster, "me", &new, &subs, "lbl", "mid", "2", 9), @@ -2641,7 +2783,11 @@ mod tests { ); for s in &subs { let row = roster.find(s, "me").unwrap(); - assert_eq!(row.address, Some(new.clone()), "{s}: new address advertised"); + assert_eq!( + row.address, + Some(new.clone()), + "{s}: new address advertised" + ); assert_eq!(row.lease_epoch, 9, "{s}: authored at the healed lease"); } } @@ -2689,12 +2835,17 @@ mod tests { // Cache: ab = stale + suspect (the strand shape); cc = valid healthy // (must be untouched); 5f = poison with no roster repair (must drop). let mut pa = PeerAddrStore::default(); - pa.put("ab", serde_json::json!({"id": "ab", "addrs": ["192.168.1.7:1"]})); + pa.put( + "ab", + serde_json::json!({"id": "ab", "addrs": ["192.168.1.7:1"]}), + ); pa.mark_suspect("ab"); let cc_addr = serde_json::json!({"id": "cc", "addrs": ["10.0.0.3:7"]}); pa.put("cc", cc_addr.clone()); - pa.addrs - .insert("5f".into(), serde_json::json!({"id": "ec", "addrs": ["10.0.0.9:1"]})); + pa.addrs.insert( + "5f".into(), + serde_json::json!({"id": "ec", "addrs": ["10.0.0.9:1"]}), + ); pa.save_to(&paths.peer_addrs).unwrap(); startup_reconcile_peeraddrs(&paths, "self"); @@ -2705,8 +2856,15 @@ mod tests { Some(&serde_json::json!({"id": "ab", "addrs": ["10.0.0.2:4711"]})), "the suspect strand healed from the roster, connection-free" ); - assert_eq!(healed.get("cc"), Some(&cc_addr), "valid row untouched by migration"); - assert!(healed.get("5f").is_none(), "unrepairable poison row dropped"); + assert_eq!( + healed.get("cc"), + Some(&cc_addr), + "valid row untouched by migration" + ); + assert!( + healed.get("5f").is_none(), + "unrepairable poison row dropped" + ); } // [unit->REQ-ONEWAY-STREAM-TERMINAL] the sender retires its OWN feed row diff --git a/crates/spt-daemon/src/pump/registry.rs b/crates/spt-daemon/src/pump/registry.rs index 5952837b..2e8a3e54 100644 --- a/crates/spt-daemon/src/pump/registry.rs +++ b/crates/spt-daemon/src/pump/registry.rs @@ -57,7 +57,11 @@ use super::{now_ms, PeerIo, PumpCadence, PumpPaths, PumpWorker, RoundCtx}; /// reason the update leg's consent notif takes this route. // [impl->REQ-SUBNET-ADMIN-RESURFACE] // [impl->REQ-HAZARD-REGISTRY-EPOCH-LEASE] -fn admin_rotation_incomplete_loudness(subnet: &str, notif_db: &std::path::Path, registry: &RegistryHost) { +fn admin_rotation_incomplete_loudness( + subnet: &str, + notif_db: &std::path::Path, + registry: &RegistryHost, +) { let body = format!( "ADMIN ROTATION INCOMPLETE for '{subnet}': the eviction window closed with no \ proven-captured pending admin key, so the member seed rotated but the OLD \ @@ -111,7 +115,10 @@ fn fire_due_rotations( let parked = pending.parked_admin(sub); match subnets.rotate_seed(sub, parked) { Ok(rec) => { - spt_proto::emit_line_err!("SEED_ROTATED:{sub}:epoch={} (revoke window closed)", rec.epoch); + spt_proto::emit_line_err!( + "SEED_ROTATED:{sub}:epoch={} (revoke window closed)", + rec.epoch + ); if parked.is_none() && rec.admin_seed_hex.is_some() { admin_rotation_incomplete_loudness(sub, notif_db, registry); } @@ -365,7 +372,10 @@ mod tests { assert!(granted.contains("\"ling\""), "granted viewer sees the row"); assert!(granted.contains("ling builds rust"), "…blurb included"); assert!(granted.contains("\"doyle\""), "ungated endpoint disclosed"); - assert!(granted.contains("hfenduleam"), "node label is not endpoint-scoped"); + assert!( + granted.contains("hfenduleam"), + "node label is not endpoint-scoped" + ); let refused = String::from_utf8(disclosable_lines(&adverts, "home", "bb22", &gate)) .expect("feed lines are utf8 ndjson"); @@ -378,7 +388,10 @@ mod tests { "…and never gets its resources blurb" ); assert!(refused.contains("\"doyle\""), "the refusal is per-endpoint"); - assert!(refused.contains("hfenduleam"), "…and does not silence labels"); + assert!( + refused.contains("hfenduleam"), + "…and does not silence labels" + ); }); } @@ -422,9 +435,13 @@ mod tests { let adverts = vec![advert("doyle"), other]; let gate = DiscoverGate::load(); - let home = String::from_utf8(disclosable_lines(&adverts, "home", "bb22", &gate)).unwrap(); + let home = + String::from_utf8(disclosable_lines(&adverts, "home", "bb22", &gate)).unwrap(); assert!(home.contains("\"doyle\"")); - assert!(!home.contains("\"ling\""), "another subnet's row is not pushed here"); + assert!( + !home.contains("\"ling\""), + "another subnet's row is not pushed here" + ); }); } @@ -447,22 +464,28 @@ mod tests { .unwrap(); let p = spt_store::engineroom::engine_room_perch(); std::fs::create_dir_all(&p).unwrap(); - let rec = spt_store::info::InfoJson::new(er, "now", std::process::id(), "s", "ready_agent"); + let rec = + spt_store::info::InfoJson::new(er, "now", std::process::id(), "s", "ready_agent"); spt_store::info::write_info(&p, &rec).unwrap(); spt_store::info::set_controlled(&p, true).unwrap(); let adverts = vec![advert(er), advert("doyle")]; let gate = DiscoverGate::load(); - let chosen = String::from_utf8(disclosable_lines(&adverts, "home", "bb22", &gate)).unwrap(); + let chosen = + String::from_utf8(disclosable_lines(&adverts, "home", "bb22", &gate)).unwrap(); assert!(chosen.contains("engine-room"), "the chosen viewer is told"); - let rest = String::from_utf8(disclosable_lines(&adverts, "home", "cc33", &gate)).unwrap(); + let rest = + String::from_utf8(disclosable_lines(&adverts, "home", "cc33", &gate)).unwrap(); assert!( !rest.contains("engine-room"), "an unchosen viewer is not told the governance surface exists: {rest}" ); - assert!(rest.contains("\"doyle\""), "and the round is otherwise unchanged"); + assert!( + rest.contains("\"doyle\""), + "and the round is otherwise unchanged" + ); }); } @@ -483,8 +506,13 @@ mod tests { let rotations_path = dir.path().join("rotation-pending.json"); let mut subnets = SubnetStore::default(); - let before_home = subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap().clone(); - subnets.create_subnet("work", spt_store::access::Mode::Open).unwrap(); + let before_home = subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap() + .clone(); + subnets + .create_subnet("work", spt_store::access::Mode::Open) + .unwrap(); subnets.save_to(&subnets_path).unwrap(); let mut pending = spt_store::rotation::RotationPending::default(); @@ -513,7 +541,11 @@ mod tests { Some(before_home.seed_hex.as_str()), "prior seed retained for the grace" ); - assert_eq!(after.find("work").unwrap().epoch, 1, "not-due subnet untouched"); + assert_eq!( + after.find("work").unwrap().epoch, + 1, + "not-due subnet untouched" + ); let pend = spt_store::rotation::RotationPending::load_from(&rotations_path); assert!(!pend.subnets.contains_key("home"), "fired entry cleared"); @@ -588,18 +620,16 @@ mod tests { spt_store::perch::ParentHint::Infer, ); std::fs::create_dir_all(&p).unwrap(); - let rec = spt_store::info::InfoJson::new( - id, - "now", - std::process::id(), - "s", - "ready_agent", - ); + let rec = + spt_store::info::InfoJson::new(id, "now", std::process::id(), "s", "ready_agent"); spt_store::info::write_info(&p, &rec).unwrap(); let subnets_path = home.join("subnet.json"); let mut subnets = SubnetStore::load(); - let before = subnets.create_subnet("rot", spt_store::access::Mode::Open).unwrap().clone(); + let before = subnets + .create_subnet("rot", spt_store::access::Mode::Open) + .unwrap() + .clone(); subnets.save().unwrap(); subnets.save_to(&subnets_path).unwrap(); diff --git a/crates/spt-daemon/src/pump/sync.rs b/crates/spt-daemon/src/pump/sync.rs index e5d0996e..5b60f03e 100644 --- a/crates/spt-daemon/src/pump/sync.rs +++ b/crates/spt-daemon/src/pump/sync.rs @@ -105,7 +105,14 @@ impl PumpWorker for SyncWorker { } if !want.is_empty() { let open_op = io.open_op()?; - let report = request_sync(&mut *io.brain, io.conn_id, &want, open_op, &cs, &self.scratch)?; + let report = request_sync( + &mut *io.brain, + io.conn_id, + &want, + open_op, + &cs, + &self.scratch, + )?; (self.on_pull)(peer_hex, &report); } Ok(()) diff --git a/crates/spt-daemon/src/pump/update.rs b/crates/spt-daemon/src/pump/update.rs index 292cbe64..fa79b5e5 100644 --- a/crates/spt-daemon/src/pump/update.rs +++ b/crates/spt-daemon/src/pump/update.rs @@ -181,7 +181,9 @@ fn advertised_update_version(body: &str) -> Option { let core = tok.trim_start_matches('v'); core.contains('.') && core.split('.').count() >= 2 - && core.split('.').all(|p| !p.is_empty() && p.chars().all(|c| c.is_ascii_digit())) + && core + .split('.') + .all(|p| !p.is_empty() && p.chars().all(|c| c.is_ascii_digit())) }) .map(str::to_string) } @@ -229,13 +231,12 @@ impl PumpWorker for UpdateWorker { retire_update_rows_the_running_image_has_passed(&store, subnet); } let base_policy = VerifyPolicy::load_from(&self.release_keys, 0, now_ms()); - let current = if cache.staged_channel().as_deref() - == Some(base_policy.pinned_channel.as_str()) - { - cache.staged_version().unwrap_or(0) - } else { - 0 - }; + let current = + if cache.staged_channel().as_deref() == Some(base_policy.pinned_channel.as_str()) { + cache.staged_version().unwrap_or(0) + } else { + 0 + }; let policy = VerifyPolicy { current_version: current, ..base_policy @@ -258,7 +259,11 @@ impl PumpWorker for UpdateWorker { .staged_version() .map(|v| v.to_string()) .unwrap_or_else(|| "?".to_string()); - spt_proto::emit_line_err!("UPDATE_STAGED:{version}:{:?} (from {})", plan.class, peer_hex); + spt_proto::emit_line_err!( + "UPDATE_STAGED:{version}:{:?} (from {})", + plan.class, + peer_hex + ); // The operator-facing version label: the signed metadata's // semver (`product_version`) when present, else the monotonic // counter — never a bare counter in the consent notif. @@ -398,7 +403,6 @@ mod tests { ); } - // [unit->REQ-NOTIF-SEAM-DISMISS] running-image vs staged product_version: // equal/ahead ⇒ caught up; behind ⇒ not; a leading `v` and a missing patch // parse; garbage on either side is conservatively `false` (never dismiss a @@ -412,7 +416,10 @@ mod tests { assert!(version_ge("0.40", "0.40.0"), "missing patch = .0"); assert!(!version_ge("0.39.4", "0.40.0"), "behind"); assert!(!version_ge("0.39.4", ""), "empty staged pv false"); - assert!(!version_ge("not-a-version", "0.40.0"), "garbage running false"); + assert!( + !version_ge("not-a-version", "0.40.0"), + "garbage running false" + ); assert!(!version_ge("0.40.0", "garbage"), "garbage staged false"); } } diff --git a/crates/spt-daemon/src/reap.rs b/crates/spt-daemon/src/reap.rs index c4b74f5e..d3db5787 100644 --- a/crates/spt-daemon/src/reap.rs +++ b/crates/spt-daemon/src/reap.rs @@ -175,7 +175,9 @@ mod windows_impl { pub fn create_kill_on_close_job() -> isize { let job = unsafe { CreateJobObjectW(std::ptr::null_mut(), std::ptr::null()) }; if job == 0 { - spt_proto::emit_line_err!("REAP_JOB_CREATE_FAIL: brain subtree will not auto-reap on stop"); + spt_proto::emit_line_err!( + "REAP_JOB_CREATE_FAIL: brain subtree will not auto-reap on stop" + ); return 0; } let mut info = JobObjectExtendedLimitInformation::default(); @@ -189,7 +191,9 @@ mod windows_impl { ) }; if ok == 0 { - spt_proto::emit_line_err!("REAP_JOB_LIMIT_FAIL: kill-on-close not set; brain subtree may orphan"); + spt_proto::emit_line_err!( + "REAP_JOB_LIMIT_FAIL: kill-on-close not set; brain subtree may orphan" + ); } job } @@ -199,7 +203,9 @@ mod windows_impl { let handle = child.as_raw_handle() as isize; let ok = unsafe { AssignProcessToJobObject(job, handle) }; if ok == 0 { - spt_proto::emit_line_err!("REAP_JOB_ASSIGN_FAIL: brain not enrolled; its subtree may orphan on stop"); + spt_proto::emit_line_err!( + "REAP_JOB_ASSIGN_FAIL: brain not enrolled; its subtree may orphan on stop" + ); } } @@ -330,8 +336,14 @@ mod tests { assert!(matches!(child.try_wait(), Ok(None)), "child starts alive"); assert!(is_process_alive(gc), "grandchild starts alive"); reaper.reap(); - assert!(wait_exit(&mut child), "reap must terminate the enrolled child"); - assert!(wait_dead(gc), "reap must terminate the inherited grandchild"); + assert!( + wait_exit(&mut child), + "reap must terminate the enrolled child" + ); + assert!( + wait_dead(gc), + "reap must terminate the inherited grandchild" + ); let _ = std::fs::remove_file(&pidfile); } @@ -363,8 +375,14 @@ mod tests { assert!(matches!(child.try_wait(), Ok(None)), "child starts alive"); assert!(is_process_alive(gc), "grandchild starts alive"); reaper.reap(); - assert!(wait_exit(&mut child), "reap must terminate the enrolled child"); - assert!(wait_dead(gc), "reap must terminate the inherited grandchild"); + assert!( + wait_exit(&mut child), + "reap must terminate the enrolled child" + ); + assert!( + wait_dead(gc), + "reap must terminate the inherited grandchild" + ); let _ = std::fs::remove_file(&pidfile); } diff --git a/crates/spt-daemon/src/redeemop.rs b/crates/spt-daemon/src/redeemop.rs index 7a2e8933..a38dd79d 100644 --- a/crates/spt-daemon/src/redeemop.rs +++ b/crates/spt-daemon/src/redeemop.rs @@ -404,13 +404,17 @@ fn impart_monic(owner: &str, peer: &str, text: &str, as_user: bool, now_ms: u64) let cs = match spt_store::contextstore::ContextStore::open_or_init() { Ok(cs) => cs, Err(e) => { - spt_proto::emit_line_err!("MONIC_IMPART_FAIL:{owner}: context store: {e} (the grant stands)"); + spt_proto::emit_line_err!( + "MONIC_IMPART_FAIL:{owner}: context store: {e} (the grant stands)" + ); return; } }; match spt_store::monic::impart_knock_monic(&cs, owner, peer, text, now_ms) { Ok(Imparted::Written) | Ok(Imparted::KeptExisting { .. }) => {} - Err(e) => spt_proto::emit_line_err!("MONIC_IMPART_FAIL:{owner}: {peer}: {e} (the grant stands)"), + Err(e) => { + spt_proto::emit_line_err!("MONIC_IMPART_FAIL:{owner}: {peer}: {e} (the grant stands)") + } } } @@ -657,7 +661,11 @@ mod tests { .list("home") .expect("rows"); assert_eq!(rows.len(), 1, "one courtesy: {rows:?}"); - assert_eq!(rows[0].to_id.as_deref(), Some("ling"), "addressed to the minter"); + assert_eq!( + rows[0].to_id.as_deref(), + Some("ling"), + "addressed to the minter" + ); assert_eq!(rows[0].from_id, "doyle", "issued by the redeemer"); assert!(rows[0].body.contains("redeemed by doyle")); assert!( @@ -1005,10 +1013,12 @@ mod tests { // arming did. The assertion could not fail for its own reason. let mut remint = KnockStore::load_checked().unwrap(); remint.codes.retain(|c| c.code != "mut00"); - remint.codes.push(mint("mut00", "ling", &[surface::MSG], false)); + remint + .codes + .push(mint("mut00", "ling", &[surface::MSG], false)); remint.save().unwrap(); - let later = serve_one_redeem(&record_with_id("r-2", "mut00", "doyle"), ORIGIN, NOW) - .unwrap(); + let later = + serve_one_redeem(&record_with_id("r-2", "mut00", "doyle"), ORIGIN, NOW).unwrap(); assert_eq!( later.outcome, spt_net::net::redeemmsg::token::REDEEMED, diff --git a/crates/spt-daemon/src/registryhost.rs b/crates/spt-daemon/src/registryhost.rs index 9289c70b..287db43b 100644 --- a/crates/spt-daemon/src/registryhost.rs +++ b/crates/spt-daemon/src/registryhost.rs @@ -263,7 +263,14 @@ impl RegistryHost { let mut flips: Vec = Vec::new(); let verdicts = { let mut regs = self.regs.lock().unwrap(); - self.merge_instances_locked(&mut regs, origin_node, updates, policy, &mut admitted_any, &mut flips) + self.merge_instances_locked( + &mut regs, + origin_node, + updates, + policy, + &mut admitted_any, + &mut flips, + ) }; // Gossip-recency stamp (M7 D2): an ADMITTED feed proves the origin // node is up right now — even a Stale merge verdict is a liveness @@ -595,9 +602,9 @@ impl RegistryHost { info.as_ref().is_some_and(|i| i.controlled), &self.node_hex, ); - let harness_only = info.as_ref().is_some_and(|i| { - i.state == "live_agent" && i.controllable != Some(true) - }); + let harness_only = info + .as_ref() + .is_some_and(|i| i.state == "live_agent" && i.controllable != Some(true)); // The #4 de-faking datums (REQ-GOSSIP-ADAPTER-PROJECTS): the endpoint's // real harness adapter + its recent projects + the EXPLICIT any-controller // truth, gossiped so `from_resource_row` stops faking remote rows. @@ -615,7 +622,8 @@ impl RegistryHost { // [impl->REQ-GOSSIP-ADAPTER-PROJECTS] let adapter = info.as_ref().and_then(|i| i.adapter.clone()); let controlled = info.as_ref().is_some_and(|i| i.controlled); - let recent_projects = recent_projects_for(&perch_path, owlery.parent().unwrap_or(owlery)); + let recent_projects = + recent_projects_for(&perch_path, owlery.parent().unwrap_or(owlery)); let last_active_ms = info.and_then(|i| i.last_active_ms); for sub in &subnets.subnets { let Ok(ep) = epoch.next_epoch() else { continue }; @@ -728,7 +736,10 @@ impl RegistryHost { endpoint_id: id, instance, })); - spt_proto::emit_line_err!("ROSTER_GHOST_HEAL:{}: erased perch advertised offline", sub.name); + spt_proto::emit_line_err!( + "ROSTER_GHOST_HEAL:{}: erased perch advertised offline", + sub.name + ); } } @@ -794,7 +805,9 @@ impl RegistryHost { for (subnet, reg) in regs.iter_mut() { let n = reg.evict_nodes(silent); if n > 0 { - spt_proto::emit_line_err!("REGISTRY_EVICT:{subnet}: {n} row(s) from silent node(s)"); + spt_proto::emit_line_err!( + "REGISTRY_EVICT:{subnet}: {n} row(s) from silent node(s)" + ); } evicted += n; } @@ -831,7 +844,9 @@ impl RegistryHost { for (subnet, reg) in regs.iter_mut() { let n = reg.evict_aged_offline(now_ms, grace_ms, &self.node_hex); if n > 0 { - spt_proto::emit_line_err!("REGISTRY_EVICT_OFFLINE:{subnet}: {n} aged-offline row(s)"); + spt_proto::emit_line_err!( + "REGISTRY_EVICT_OFFLINE:{subnet}: {n} aged-offline row(s)" + ); } evicted += n; } @@ -1340,7 +1355,10 @@ mod tests { assert_eq!(got, vec!["alpha", "beta", "gamma"], "got {got:?}"); // [unit->REQ-ER-SEQUESTERED-CWD] stated as its own claim rather than left to // the vec equality above: the engine room's cwd is not gossiped as a project. - assert!(!got.iter().any(|p| p == "cwd"), "engine-room cwd gossiped: {got:?}"); + assert!( + !got.iter().any(|p| p == "cwd"), + "engine-room cwd gossiped: {got:?}" + ); } fn ledger_entry(sid: &str, cwd: &str) -> spt_store::sessions::SessionEntry { @@ -1410,10 +1428,15 @@ mod tests { dir.file_name().unwrap().to_string_lossy().into_owned() }); // Newest 8 projects win despite every cwd having a duplicate row. - let want: Vec = (0..MAX_GOSSIPED_PROJECTS).map(|k| format!("p{:02}", 11 - k)).collect(); + let want: Vec = (0..MAX_GOSSIPED_PROJECTS) + .map(|k| format!("p{:02}", 11 - k)) + .collect(); assert_eq!(got, want, "got {got:?}"); // Scan stopped at the cap: 8 derivations, not 12 (and never 24). - assert_eq!(derivations, MAX_GOSSIPED_PROJECTS, "derivations {derivations}"); + assert_eq!( + derivations, MAX_GOSSIPED_PROJECTS, + "derivations {derivations}" + ); } // [unit->REQ-GOSSIP-CONTROLLED-ANY] bug #3: a locally-controlled endpoint @@ -1615,8 +1638,7 @@ mod tests { label: "BOX".into(), machine_id: "mid-1".into(), }; - let notices = - repair_evict_superseded(&mut roster, "home", "new-key", &intro, &snap_dir); + let notices = repair_evict_superseded(&mut roster, "home", "new-key", &intro, &snap_dir); // The demoted warn-on-change: one machine_id-anchored notice K1→K2. assert_eq!( @@ -1667,7 +1689,10 @@ mod tests { }; let none = repair_evict_superseded(&mut r2, "home", "new-key", &other, &snap_dir); assert!(none.is_empty(), "no-match raises no rekey notice"); - assert!(r2.is_member("home", "unrelated"), "no-match leaves roster intact"); + assert!( + r2.is_member("home", "unrelated"), + "no-match leaves roster intact" + ); assert!(!RegistryHost::repair_evict_path(&snap_dir).exists()); // Absent machine id: a FRESH gossip snapshot with a labeled identity; @@ -1697,7 +1722,10 @@ mod tests { }; let silent = repair_evict_superseded(&mut r3, "home", "new-key", &no_id, &snap2); assert!(silent.is_empty(), "absent machine id → no false notice"); - assert!(r3.is_member("home", "old2"), "absent-id leaves roster intact"); + assert!( + r3.is_member("home", "old2"), + "absent-id leaves roster intact" + ); } // [unit->REQ-INST-7] inbound feeds gate fail-closed: non-member subnet @@ -1747,7 +1775,9 @@ mod tests { info::set_resources(&authored, Some("rust builds")).unwrap(); let mut subnets = SubnetStore::load(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); // The node seed: daemon.json under the canonical home. let cfg = crate::config::DaemonConfig { @@ -1874,7 +1904,9 @@ mod tests { info::set_last_active(&stamped, 7_000).unwrap(); let mut subnets = SubnetStore::load(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let h = host(home); @@ -2044,10 +2076,15 @@ mod tests { ); // The label landed and is the only carrier — no endpoint row created. let snap = RegistryHost::snapshot_path(&dir.path().join("registry"), "home"); - let reg: SubnetRegistry = - serde_json::from_slice(&std::fs::read(&snap).unwrap()).unwrap(); - assert_eq!(reg.node_labels().collect::>(), vec![("bb22", "RENAMED")]); - assert!(reg.endpoint_ids().next().is_none(), "no phantom endpoint row"); + let reg: SubnetRegistry = serde_json::from_slice(&std::fs::read(&snap).unwrap()).unwrap(); + assert_eq!( + reg.node_labels().collect::>(), + vec![("bb22", "RENAMED")] + ); + assert!( + reg.endpoint_ids().next().is_none(), + "no phantom endpoint row" + ); } // [unit->REQ-REGISTRY-APPLY-TRANSACTIONAL] the transactional batch apply @@ -2111,7 +2148,10 @@ mod tests { 1, "one batch = one snapshot write, never per record-kind" ); - assert_eq!(merged, 4, "every record judged (refusals count as verdicts)"); + assert_eq!( + merged, 4, + "every record judged (refusals count as verdicts)" + ); assert!(flips.is_empty(), "inserts are not attention flips"); // Parity: the twin applies the SAME records through the per-kind @@ -2131,7 +2171,9 @@ mod tests { ); // The refused record never landed on either host. assert!( - snap(&h, &dir.path().join("batch")).instances("ghost").is_empty(), + snap(&h, &dir.path().join("batch")) + .instances("ghost") + .is_empty(), "the per-record gate refused inside the batch" ); @@ -2143,7 +2185,11 @@ mod tests { // Flip parity too: a Dormant→Active transition observed through the // BATCH path reports the flip exactly like the per-kind path. let (_, flips) = h.apply_feed_batch("bb22", &[], &[inst("doyle", Status::Active, 3)], &p); - assert_eq!(flips, vec!["doyle".to_string()], "flip detection rides the batch"); + assert_eq!( + flips, + vec!["doyle".to_string()], + "flip detection rides the batch" + ); } // [unit->REQ-INST-3] registry advertisement FOLLOWS the resting-state @@ -2160,7 +2206,9 @@ mod tests { let rec = InfoJson::new("ling", "now", std::process::id(), "s", "live_agent"); info::write_info(&p, &rec).unwrap(); let mut subnets = SubnetStore::load(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let h = host(home); @@ -2309,9 +2357,14 @@ mod tests { &InfoJson::new("live", "now", std::process::id(), "s", "live_agent"), ) .unwrap(); - assert_eq!(advertised_status(&p), Status::Active, "baseline: bound+alive ⇒ Active"); + assert_eq!( + advertised_status(&p), + Status::Active, + "baseline: bound+alive ⇒ Active" + ); // Stamp a host-level failure report — the derivation must not change. - info::set_host_error(&p, Some("wake-resume: adapter 'ghost' is not registered")).unwrap(); + info::set_host_error(&p, Some("wake-resume: adapter 'ghost' is not registered")) + .unwrap(); assert_eq!( advertised_status(&p), Status::Active, @@ -2334,7 +2387,9 @@ mod tests { let rec = InfoJson::new("ghost-ag", "now", std::process::id(), "s", "ready_agent"); info::write_info(&p, &rec).unwrap(); let mut subnets = SubnetStore::load(); - subnets.create_subnet("adv", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("adv", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let h = host(home); @@ -2364,10 +2419,10 @@ mod tests { "offline heal advertised to peers: {out:?}" ); // No longer a routable (Active) resource → resource_projection drops it. - let rows = spt_net::net::registry::resource_projection( - &h.regs.lock().unwrap()["adv"], - |_| false, - ); + let rows = + spt_net::net::registry::resource_projection(&h.regs.lock().unwrap()["adv"], |_| { + false + }); assert!( rows.iter().all(|r| r.endpoint_id != "ghost-ag"), "erased endpoint no longer projects as a live resource" @@ -2388,7 +2443,9 @@ mod tests { info::write_info(&p, &rec).unwrap(); } let mut subnets = SubnetStore::load(); - subnets.create_subnet("adv", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("adv", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let mut vis = VisibilityStore::load(); vis.set_override("hid-ag", "adv", Some(true)); // hidden ⇒ excluded @@ -2562,12 +2619,19 @@ mod tests { // the ghost survives (eviction must not race a row that just went Offline). assert_eq!(h.evict_aged_offline_rows_at(grace, 1_000), 0); assert_eq!(h.evict_aged_offline_rows_at(grace, 1_000 + 299_000), 0); - assert_eq!(h.rows("home", "ghost").len(), 1, "within grace the ghost survives"); + assert_eq!( + h.rows("home", "ghost").len(), + 1, + "within grace the ghost survives" + ); // Past the grace the aged Offline ghost evicts and the snapshot is rewritten. let later = 1_000 + 300_000 + 1; assert_eq!(h.evict_aged_offline_rows_at(grace, later), 1); - assert!(h.rows("home", "ghost").is_empty(), "aged Offline ghost evicted"); + assert!( + h.rows("home", "ghost").is_empty(), + "aged Offline ghost evicted" + ); let snap = RegistryHost::snapshot_path(&dir.path().join("registry"), "home"); let parsed: SubnetRegistry = serde_json::from_slice(&std::fs::read(&snap).unwrap()).unwrap(); @@ -2592,7 +2656,9 @@ mod tests { let rec = InfoJson::new("mine", "now", std::process::id(), "s", "ready_agent"); info::write_info(&p, &rec).unwrap(); let mut subnets = SubnetStore::load(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let h = host(home); // node_hex = "aa11", never in heard @@ -2626,7 +2692,9 @@ mod tests { let rec = InfoJson::new("lab-ag", "now", std::process::id(), "s", "ready_agent"); info::write_info(&p, &rec).unwrap(); let mut subnets = SubnetStore::load(); - subnets.create_subnet("lab", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("lab", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let instance_row = |out: &[RegistryFeedRecord], id: &str| { diff --git a/crates/spt-daemon/src/relay.rs b/crates/spt-daemon/src/relay.rs index a2174bc0..5464947d 100644 --- a/crates/spt-daemon/src/relay.rs +++ b/crates/spt-daemon/src/relay.rs @@ -62,8 +62,11 @@ impl Relay { /// killed one left behind. Returns the number of messages forwarded. pub fn drain_backlog(&self, mut sink: F) -> usize { // [impl->REQ-SPOOL-TAKE-AUDIT] relay-backlog leg — stamp who drained the row. - let audit = - spool::TakerAudit::new(spool::TakerLeg::RelayBacklog, None, Some(std::process::id())); + let audit = spool::TakerAudit::new( + spool::TakerLeg::RelayBacklog, + None, + Some(std::process::id()), + ); // DRAIN-TIME NOTIF VALIDITY (ADR-0046 Amendment 1, KH 7.53): this is the // INJECTING presentation — a stale spooled notice here wakes the agent // with a fact that is no longer true (perri's field report). The gate is diff --git a/crates/spt-daemon/src/release.rs b/crates/spt-daemon/src/release.rs index 982069b6..34ca9727 100644 --- a/crates/spt-daemon/src/release.rs +++ b/crates/spt-daemon/src/release.rs @@ -397,7 +397,9 @@ impl VerifyPolicy { trusted_keys.insert(key_id.to_string(), vk); } // A bad builtin entry is a build defect — loud, never silent. - Err(_) => spt_proto::emit_line_err!("RELEASE_KEY_BAD:builtin:{key_id} — skipped (not a valid key)"), + Err(_) => spt_proto::emit_line_err!( + "RELEASE_KEY_BAD:builtin:{key_id} — skipped (not a valid key)" + ), } } for (key_id, hex) in &file.keys { @@ -405,7 +407,9 @@ impl VerifyPolicy { Ok(vk) => { trusted_keys.insert(key_id.clone(), vk); } - Err(_) => spt_proto::emit_line_err!("RELEASE_KEY_BAD:{key_id} — skipped (not a valid key)"), + Err(_) => spt_proto::emit_line_err!( + "RELEASE_KEY_BAD:{key_id} — skipped (not a valid key)" + ), } } VerifyPolicy { @@ -618,7 +622,11 @@ fn check_signature( /// adapter's declared `signing_key`. **Fail-closed:** any malformed signature or /// mismatch returns an error and the bytes are never trusted (REQ-UPD-9). // [impl->REQ-UPD-9] -pub fn verify_detached(bytes: &[u8], signature_hex: &str, key: &VerifyingKey) -> Result<(), RejectReason> { +pub fn verify_detached( + bytes: &[u8], + signature_hex: &str, + key: &VerifyingKey, +) -> Result<(), RejectReason> { let sig_bytes = hex_decode(signature_hex).map_err(RejectReason::Malformed)?; let sig_arr: [u8; 64] = sig_bytes.as_slice().try_into().map_err(|_| { RejectReason::Malformed(format!("signature is {} bytes, want 64", sig_bytes.len())) @@ -659,10 +667,7 @@ pub fn verify_artifact(meta: &ReleaseMetadata, artifact: &[u8]) -> Result<(), Re /// update set. The caller treats a mismatch as SKIP-the-docs, never as a /// release rejection (ADR-0036 §4 failure isolation). // [impl->REQ-DOCS-RELEASE-ASSET] -pub fn verify_update_set_docs( - meta: &UpdateSetMetadata, - bundle: &[u8], -) -> Result<(), RejectReason> { +pub fn verify_update_set_docs(meta: &UpdateSetMetadata, bundle: &[u8]) -> Result<(), RejectReason> { let Some(docs) = &meta.docs else { return Err(RejectReason::Malformed("set carries no docs entry".into())); }; diff --git a/crates/spt-daemon/src/resting.rs b/crates/spt-daemon/src/resting.rs index 8d5eb510..3e5c8bda 100644 --- a/crates/spt-daemon/src/resting.rs +++ b/crates/spt-daemon/src/resting.rs @@ -594,10 +594,14 @@ pub fn route_rest_event( Ok(report) => RestRoute::Local(report), Err(e) if allow_remote_fallback && e.contains(NOT_A_HOSTED_PERCH_MARKER) => { let goal = match event { - RestEvent::Wake => RestGoal { target: Status::Active, kind: GoalKind::Exists }, - RestEvent::Suspend => { - RestGoal { target: Status::Suspended, kind: GoalKind::Forall } - } + RestEvent::Wake => RestGoal { + target: Status::Active, + kind: GoalKind::Exists, + }, + RestEvent::Suspend => RestGoal { + target: Status::Suspended, + kind: GoalKind::Forall, + }, _ => return RestRoute::NoRemoteArm, }; match select_rest_target(&load_candidates(), goal) { @@ -627,9 +631,8 @@ mod tests { fn route_rest_event_contract_table() { use spt_net::net::registry::Status; let miss = || Err(format!("info.json absent — {NOT_A_HOSTED_PERCH_MARKER}")); - let no_candidates_expected = || -> Vec<(String, Status)> { - panic!("load_candidates must not run on a local path") - }; + let no_candidates_expected = + || -> Vec<(String, Status)> { panic!("load_candidates must not run on a local path") }; // Local edge + local no-edge pass through, candidates never loaded. assert!(matches!( @@ -956,7 +959,10 @@ mod tests { assert_eq!(effective_rest_state(true, false, None), Active); assert_eq!(effective_rest_state(true, false, Some(Active)), Active); assert_eq!(effective_rest_state(true, false, Some(Dormant)), Dormant); - assert_eq!(effective_rest_state(true, false, Some(Suspended)), Suspended); + assert_eq!( + effective_rest_state(true, false, Some(Suspended)), + Suspended + ); // unbound (warm skeleton): Dormant for EVERY intent, incl. void. for intent in [None, Some(Active), Some(Dormant), Some(Suspended)] { @@ -1045,7 +1051,10 @@ mod tests { // idempotent answer when no live session exists). let report = apply_event(d.path(), RestEvent::Suspend, None, 1_000, || Ok(()), || {}) .expect("apply ok"); - assert!(report.is_none(), "no hint + cold perch ⇒ idempotent NO_EDGE"); + assert!( + report.is_none(), + "no hint + cold perch ⇒ idempotent NO_EDGE" + ); // WITH the broker-truth hint (a live non-zombie session exists): the // Suspend is a REAL edge — shutdown answers from the same authority diff --git a/crates/spt-daemon/src/rollback_compat.rs b/crates/spt-daemon/src/rollback_compat.rs index aa703a54..1ac05263 100644 --- a/crates/spt-daemon/src/rollback_compat.rs +++ b/crates/spt-daemon/src/rollback_compat.rs @@ -125,16 +125,29 @@ mod tests { candidate_started_ms: 1_234, prior_version: Some(6), }, - &["phase", "version", "rollback_binary", "candidate_started_ms"], + &[ + "phase", + "version", + "rollback_binary", + "candidate_started_ms", + ], + ); + assert_additive_n1_readable( + &AppliedRecord::Applied { version: 7 }, + &["phase", "version"], ); - assert_additive_n1_readable(&AppliedRecord::Applied { version: 7 }, &["phase", "version"]); assert_additive_n1_readable( &AppliedRecord::RolledBack { quarantine_version: 7, running_version: 6, rollback_binary: "/opt/spt/spt.old-6".to_string(), }, - &["phase", "quarantine_version", "running_version", "rollback_binary"], + &[ + "phase", + "quarantine_version", + "running_version", + "rollback_binary", + ], ); // D6-1b + D7-1: brain.ready (`{pid, generation, exe_hash}`) — no struct; @@ -145,7 +158,9 @@ mod tests { let ready = serde_json::json!({ "pid": 4321, "generation": 9, "exe_hash": "ab12" }); let obj = ready.as_object().unwrap(); assert!( - obj.contains_key("pid") && obj.contains_key("generation") && obj.contains_key("exe_hash") + obj.contains_key("pid") + && obj.contains_key("generation") + && obj.contains_key("exe_hash") ); let with_extra = serde_json::json!({ "pid": 4321, "generation": 9, "exe_hash": "ab12", "spt_future_additive_field": "x" diff --git a/crates/spt-daemon/src/sealsync.rs b/crates/spt-daemon/src/sealsync.rs index d12a6181..d4e31c87 100644 --- a/crates/spt-daemon/src/sealsync.rs +++ b/crates/spt-daemon/src/sealsync.rs @@ -121,21 +121,15 @@ pub fn apply_seal_feed( records .iter() .map(|wire| match wire { - SealWireRecord::Seal { record } => { - match gate(record.binding_subnet().as_deref()) { - Err(verdict) => verdict, - Ok(()) => SealApplyVerdict::Applied(store.merge_record(record.clone())), - } - } + SealWireRecord::Seal { record } => match gate(record.binding_subnet().as_deref()) { + Err(verdict) => verdict, + Ok(()) => SealApplyVerdict::Applied(store.merge_record(record.clone())), + }, // [impl->REQ-SEAL-ENROLL-RECORD-SUBNET-MATERIAL] - SealWireRecord::SealEnrollment { record } => { - match gate(Some(record.subnet.as_str())) { - Err(verdict) => verdict, - Ok(()) => { - SealApplyVerdict::AppliedEnrollment(enrolls.merge_record(record.clone())) - } - } - } + SealWireRecord::SealEnrollment { record } => match gate(Some(record.subnet.as_str())) { + Err(verdict) => verdict, + Ok(()) => SealApplyVerdict::AppliedEnrollment(enrolls.merge_record(record.clone())), + }, }) .collect() } @@ -182,17 +176,30 @@ mod tests { let minted = mint_seal(&mut a, b"ship it", "home:ling@aa11", "test", 1_000).unwrap(); let mut b = SealStore::default(); - let records = SealFeedDecoder::new().push(&emit_seal_feed(&a, &EnrollStore::default(), "home")); + let records = + SealFeedDecoder::new().push(&emit_seal_feed(&a, &EnrollStore::default(), "home")); assert_eq!(records.len(), 1); let policy = trusting(&["home"], "nodea-hex"); - let verdicts = apply_seal_feed(&mut b, &mut EnrollStore::default(), "nodea-hex", &records, &policy); + let verdicts = apply_seal_feed( + &mut b, + &mut EnrollStore::default(), + "nodea-hex", + &records, + &policy, + ); assert_eq!( verdicts, vec![SealApplyVerdict::Applied(SealMergeOutcome::Inserted)] ); assert_eq!(b.find(&minted.token), Some(&minted), "converged"); - let replay = apply_seal_feed(&mut b, &mut EnrollStore::default(), "nodea-hex", &records, &policy); + let replay = apply_seal_feed( + &mut b, + &mut EnrollStore::default(), + "nodea-hex", + &records, + &policy, + ); assert_eq!( replay, vec![SealApplyVerdict::Applied(SealMergeOutcome::Unchanged)], @@ -210,7 +217,8 @@ mod tests { let home = mint_seal(&mut a, b"one", "home:ling@aa11", "test", 1).unwrap(); let work = mint_seal(&mut a, b"two", "work:ling@aa11", "test", 2).unwrap(); - let feed = SealFeedDecoder::new().push(&emit_seal_feed(&a, &EnrollStore::default(), "home")); + let feed = + SealFeedDecoder::new().push(&emit_seal_feed(&a, &EnrollStore::default(), "home")); let tokens: Vec<&str> = feed .iter() .filter_map(|wire| match wire { @@ -231,8 +239,10 @@ mod tests { let mut a = SealStore::default(); mint_seal(&mut a, b"one", "home:ling@aa11", "test", 1).unwrap(); mint_seal(&mut a, b"two", "work:ling@aa11", "test", 2).unwrap(); - let home = SealFeedDecoder::new().push(&emit_seal_feed(&a, &EnrollStore::default(), "home")); - let work = SealFeedDecoder::new().push(&emit_seal_feed(&a, &EnrollStore::default(), "work")); + let home = + SealFeedDecoder::new().push(&emit_seal_feed(&a, &EnrollStore::default(), "home")); + let work = + SealFeedDecoder::new().push(&emit_seal_feed(&a, &EnrollStore::default(), "work")); // Wholly untrusted origin: dropped, nothing written. let mut b = SealStore::default(); @@ -240,14 +250,26 @@ mod tests { subnets: vec!["home".into()], roster: RosterStore::default(), }; - let verdicts = apply_seal_feed(&mut b, &mut EnrollStore::default(), "evil-hex", &home, &unpaired); + let verdicts = apply_seal_feed( + &mut b, + &mut EnrollStore::default(), + "evil-hex", + &home, + &unpaired, + ); assert_eq!(verdicts, vec![SealApplyVerdict::DroppedUntrusted]); assert!(b.records.is_empty(), "zero records written"); // Trusted in home only, member of both: the work-bound seal still drops. let mut policy = trusting(&["home"], "nodea-hex"); policy.subnets.push("work".into()); - let verdicts = apply_seal_feed(&mut b, &mut EnrollStore::default(), "nodea-hex", &work, &policy); + let verdicts = apply_seal_feed( + &mut b, + &mut EnrollStore::default(), + "nodea-hex", + &work, + &policy, + ); assert_eq!( verdicts, vec![SealApplyVerdict::DroppedUntrusted], @@ -263,12 +285,19 @@ mod tests { fn non_member_subnet_record_never_materializes() { let mut a = SealStore::default(); mint_seal(&mut a, b"x", "elsewhere:ling@aa11", "test", 1).unwrap(); - let records = SealFeedDecoder::new().push(&emit_seal_feed(&a, &EnrollStore::default(), "elsewhere")); + let records = + SealFeedDecoder::new().push(&emit_seal_feed(&a, &EnrollStore::default(), "elsewhere")); let mut b = SealStore::default(); let mut policy = trusting(&["home"], "nodea-hex"); policy.roster.merge_entry(member("elsewhere", "nodea-hex")); - let verdicts = apply_seal_feed(&mut b, &mut EnrollStore::default(), "nodea-hex", &records, &policy); + let verdicts = apply_seal_feed( + &mut b, + &mut EnrollStore::default(), + "nodea-hex", + &records, + &policy, + ); assert_eq!(verdicts, vec![SealApplyVerdict::DroppedNonMember]); assert!(b.records.is_empty(), "never materialized"); } @@ -286,7 +315,7 @@ mod tests { minter: "home:ling@aa11".into(), minted_at: 1, ceremony_kind: "test".into(), - signature_hex: None, + signature_hex: None, }; b.merge_record(held.clone()); @@ -294,10 +323,18 @@ mod tests { forged.content_hash = "bb".repeat(32); let records = vec![SealWireRecord::Seal { record: forged }]; let policy = trusting(&["home"], "nodea-hex"); - let verdicts = apply_seal_feed(&mut b, &mut EnrollStore::default(), "nodea-hex", &records, &policy); + let verdicts = apply_seal_feed( + &mut b, + &mut EnrollStore::default(), + "nodea-hex", + &records, + &policy, + ); assert_eq!( verdicts, - vec![SealApplyVerdict::Applied(SealMergeOutcome::CollisionDropped)] + vec![SealApplyVerdict::Applied( + SealMergeOutcome::CollisionDropped + )] ); assert_eq!(b.find("abcdefghjk"), Some(&held), "existing kept"); } @@ -320,15 +357,33 @@ mod tests { #[test] fn enrollment_feed_converges_scoped_and_replay_noops() { let mut seals_a = SealStore::default(); - let minted = - mint_seal(&mut seals_a, b"ship it", "home:ling@aa11", "test", 1_000).unwrap(); + let minted = mint_seal(&mut seals_a, b"ship it", "home:ling@aa11", "test", 1_000).unwrap(); let mut enrolls_a = EnrollStore::default(); - let home = mint_enrollment(&mut enrolls_a, "abcd", "aa11bb22", "home", "hello-kcm-rs256", 1) - .unwrap(); - mint_enrollment(&mut enrolls_a, "abcd", "aa11bb22", "work", "hello-kcm-rs256", 2).unwrap(); + let home = mint_enrollment( + &mut enrolls_a, + "abcd", + "aa11bb22", + "home", + "hello-kcm-rs256", + 1, + ) + .unwrap(); + mint_enrollment( + &mut enrolls_a, + "abcd", + "aa11bb22", + "work", + "hello-kcm-rs256", + 2, + ) + .unwrap(); let feed = SealFeedDecoder::new().push(&emit_seal_feed(&seals_a, &enrolls_a, "home")); - assert_eq!(feed.len(), 2, "the home seal + the home enrollment, not work's"); + assert_eq!( + feed.len(), + 2, + "the home seal + the home enrollment, not work's" + ); let mut seals_b = SealStore::default(); let mut enrolls_b = EnrollStore::default(); @@ -342,8 +397,16 @@ mod tests { ] ); assert_eq!(seals_b.find(&minted.token), Some(&minted), "seal converged"); - assert_eq!(enrolls_b.find("aa11bb22", "home"), Some(&home), "enrollment converged"); - assert_eq!(enrolls_b.find("aa11bb22", "work"), None, "work stayed off the home feed"); + assert_eq!( + enrolls_b.find("aa11bb22", "home"), + Some(&home), + "enrollment converged" + ); + assert_eq!( + enrolls_b.find("aa11bb22", "work"), + None, + "work stayed off the home feed" + ); let replay = apply_seal_feed(&mut seals_b, &mut enrolls_b, "nodea-hex", &feed, &policy); assert_eq!( @@ -400,9 +463,15 @@ mod tests { let verdicts = apply_seal_feed(&mut seals, &mut enrolls, "nodea-hex", &wire, &policy); assert_eq!( verdicts, - vec![SealApplyVerdict::AppliedEnrollment(EnrollMergeOutcome::CollisionDropped)] + vec![SealApplyVerdict::AppliedEnrollment( + EnrollMergeOutcome::CollisionDropped + )] + ); + assert_eq!( + enrolls.find("aa11bb22", "home"), + Some(&held), + "existing kept" ); - assert_eq!(enrolls.find("aa11bb22", "home"), Some(&held), "existing kept"); } // [unit->REQ-SEAL-STORE-REPLICATES-SUBNET-SCOPED] a record whose minter @@ -422,7 +491,13 @@ mod tests { }, }]; let policy = trusting(&["home"], "nodea-hex"); - let verdicts = apply_seal_feed(&mut b, &mut EnrollStore::default(), "nodea-hex", &records, &policy); + let verdicts = apply_seal_feed( + &mut b, + &mut EnrollStore::default(), + "nodea-hex", + &records, + &policy, + ); assert_eq!(verdicts, vec![SealApplyVerdict::DroppedUnscoped]); assert!(b.records.is_empty()); } diff --git a/crates/spt-daemon/src/seedmap.rs b/crates/spt-daemon/src/seedmap.rs index 82e31d51..69300747 100644 --- a/crates/spt-daemon/src/seedmap.rs +++ b/crates/spt-daemon/src/seedmap.rs @@ -447,7 +447,10 @@ mod tests { }); for _ in 0..400 { if ping(&name).is_ok() { - return SeedServer { name, stopped: false }; + return SeedServer { + name, + stopped: false, + }; } std::thread::sleep(Duration::from_millis(5)); } diff --git a/crates/spt-daemon/src/seedproofx.rs b/crates/spt-daemon/src/seedproofx.rs index 48f0a461..1723d64d 100644 --- a/crates/spt-daemon/src/seedproofx.rs +++ b/crates/spt-daemon/src/seedproofx.rs @@ -280,8 +280,7 @@ pub async fn prove_membership( ProofRole::Dialer => (local_id, remote), ProofRole::Acceptor => (remote, local_id), }; - let by_name: HashMap<&str, &SubnetCred> = - creds.iter().map(|c| (c.name.as_str(), c)).collect(); + let by_name: HashMap<&str, &SubnetCred> = creds.iter().map(|c| (c.name.as_str(), c)).collect(); match role { ProofRole::Dialer => { @@ -338,7 +337,10 @@ impl LocalGens { /// The `(epoch, tag)` set this node sends for the subnet, proving each /// generation it holds in role `mine` (current first). fn outbound(&self, mine: ProofRole) -> Vec<(u64, [u8; 32])> { - let mut out = vec![(self.current.epoch, self.current.transcript.tag(&self.current.mk, mine))]; + let mut out = vec![( + self.current.epoch, + self.current.transcript.tag(&self.current.mk, mine), + )]; if let Some(p) = &self.prev { out.push((p.epoch, p.transcript.tag(&p.mk, mine))); } @@ -402,10 +404,24 @@ fn build_gens( for name in shared { let cred = by_name.get(name.as_str())?; let current = gen_proof( - &cred.seed, name, cred.epoch, dialer_pub, acceptor_pub, nonce_d, nonce_a, + &cred.seed, + name, + cred.epoch, + dialer_pub, + acceptor_pub, + nonce_d, + nonce_a, ); let prev = cred.prev.as_ref().map(|(seed, epoch)| { - gen_proof(seed, name, *epoch, dialer_pub, acceptor_pub, nonce_d, nonce_a) + gen_proof( + seed, + name, + *epoch, + dialer_pub, + acceptor_pub, + nonce_d, + nonce_a, + ) }); out.push(LocalGens { name: name.clone(), @@ -418,7 +434,11 @@ fn build_gens( /// This peer's roster status for a subnet, via the (opt-in) roster seam. `None` /// when no seam is wired — the mechanics-only path grades on epoch alone. -fn peer_status(roster: Option<&RosterExchange>, subnet: &str, peer_hex: &str) -> Option { +fn peer_status( + roster: Option<&RosterExchange>, + subnet: &str, + peer_hex: &str, +) -> Option { roster.map(|rx| (rx.member_status)(subnet, peer_hex)) } @@ -469,12 +489,22 @@ async fn prove_as_dialer( ) -> Option> { let nonce_d = fresh_nonce(); let my_names: Vec = creds.iter().map(|c| c.name.clone()).collect(); - write_frame(send, &SeedProofFrame::Hello { nonce: nonce_d, subnets: my_names }.encode()) - .await?; + write_frame( + send, + &SeedProofFrame::Hello { + nonce: nonce_d, + subnets: my_names, + } + .encode(), + ) + .await?; // Acceptor replies with the intersection (in its order) + its nonce. stage.enter(STAGE_PROOF_RECV); - let (nonce_a, shared) = match read_frame(recv, MAX_FRAME).await.and_then(|b| SeedProofFrame::decode(&b)) { + let (nonce_a, shared) = match read_frame(recv, MAX_FRAME) + .await + .and_then(|b| SeedProofFrame::decode(&b)) + { Some(SeedProofFrame::Hello { nonce, subnets }) => (nonce, subnets), _ => return None, }; @@ -491,8 +521,14 @@ async fn prove_as_dialer( // They buffer while the acceptor reads, so the ping-pong never deadlocks. stage.enter(STAGE_PROOF_SEND); for g in &gens { - write_frame(send, &SeedProofFrame::ProofSet { proofs: g.outbound(ProofRole::Dialer) }.encode()) - .await?; + write_frame( + send, + &SeedProofFrame::ProofSet { + proofs: g.outbound(ProofRole::Dialer), + } + .encode(), + ) + .await?; } // Then read the acceptor's proof sets (no early abort — grade after the full // read so the legs below stay symmetric with the acceptor; tombstone grading @@ -500,7 +536,10 @@ async fn prove_as_dialer( stage.enter(STAGE_PROOF_RECV); let mut peer_sets = Vec::with_capacity(gens.len()); for _ in &gens { - match read_frame(recv, MAX_FRAME).await.and_then(|b| SeedProofFrame::decode(&b)) { + match read_frame(recv, MAX_FRAME) + .await + .and_then(|b| SeedProofFrame::decode(&b)) + { Some(SeedProofFrame::ProofSet { proofs }) => peer_sets.push(proofs), _ => return None, } @@ -545,7 +584,10 @@ async fn prove_as_acceptor( roster: Option<&RosterExchange>, self_addr: &serde_json::Value, ) -> Option> { - let (nonce_d, dialer_names) = match read_frame(recv, MAX_FRAME).await.and_then(|b| SeedProofFrame::decode(&b)) { + let (nonce_d, dialer_names) = match read_frame(recv, MAX_FRAME) + .await + .and_then(|b| SeedProofFrame::decode(&b)) + { Some(SeedProofFrame::Hello { nonce, subnets }) => (nonce, subnets), _ => return None, }; @@ -560,7 +602,11 @@ async fn prove_as_acceptor( let nonce_a = fresh_nonce(); write_frame( send, - &SeedProofFrame::Hello { nonce: nonce_a, subnets: shared.clone() }.encode(), + &SeedProofFrame::Hello { + nonce: nonce_a, + subnets: shared.clone(), + } + .encode(), ) .await?; if shared.is_empty() { @@ -574,14 +620,23 @@ async fn prove_as_acceptor( // send-then-read, so the ping-pong stays deadlock-free). let mut peer_sets = Vec::with_capacity(gens.len()); for _ in &gens { - match read_frame(recv, MAX_FRAME).await.and_then(|b| SeedProofFrame::decode(&b)) { + match read_frame(recv, MAX_FRAME) + .await + .and_then(|b| SeedProofFrame::decode(&b)) + { Some(SeedProofFrame::ProofSet { proofs }) => peer_sets.push(proofs), _ => return None, } } for g in &gens { - write_frame(send, &SeedProofFrame::ProofSet { proofs: g.outbound(ProofRole::Acceptor) }.encode()) - .await?; + write_frame( + send, + &SeedProofFrame::ProofSet { + proofs: g.outbound(ProofRole::Acceptor), + } + .encode(), + ) + .await?; } let graded = grade_all(&gens, &peer_sets, ProofRole::Dialer, remote_hex, roster); @@ -594,7 +649,9 @@ async fn prove_as_acceptor( /// Write a length-delimited frame (`u32` BE length prefix + body). async fn write_frame(send: &mut SendStream, body: &[u8]) -> Option<()> { - send.write_all(&(body.len() as u32).to_be_bytes()).await.ok()?; + send.write_all(&(body.len() as u32).to_be_bytes()) + .await + .ok()?; send.write_all(body).await.ok()?; Some(()) } @@ -628,8 +685,11 @@ async fn read_frame(recv: &mut RecvStream, max: usize) -> Option> { /// live address (`self_addr`) onto its advertised self-entry so peers learn how /// to reach it. `proven` is the set both sides verified; `self_addr` is the /// opaque dialable-address JSON (`Null` ⇒ advertise no address). -pub type RosterProvider = - Arc, &serde_json::Value) -> (Vec, Vec) + Send + Sync>; +pub type RosterProvider = Arc< + dyn Fn(&HashSet, &serde_json::Value) -> (Vec, Vec) + + Send + + Sync, +>; /// Merges a received roster slice into the durable store and reconciles the dial /// cache (gap-fill). Receives the peer's advertised entries + tombstones. @@ -682,7 +742,10 @@ async fn exchange_roster_dialer( // desyncs against a peer that does. `proven` is empty ⇒ an empty slice. let Some(rx) = roster else { return }; let (entries, tombstones) = (rx.provider)(proven, self_addr); - if write_frame(send, &enc_roster(&entries, &tombstones)).await.is_none() { + if write_frame(send, &enc_roster(&entries, &tombstones)) + .await + .is_none() + { return; } if let Some(body) = read_frame(recv, MAX_FRAME).await { @@ -1097,62 +1160,74 @@ pub fn production_roster_exchange() -> RosterExchange { // source is owned here instead. let epochs = Arc::new(Mutex::new(spt_store::epoch::EpochSource::load())); RosterExchange { - provider: Arc::new(move |proven: &HashSet, self_addr: &serde_json::Value| { - let mut store = RosterStore::load(); - let label = spt_store::hostlabel::os_hostname().unwrap_or_default(); - let machine_id = crate::machineid::machine_id_hash().unwrap_or_default(); - // Peek, never consume: roster propagation must not disturb the - // registry lease counter (the D3 rule). The heal may FAST-FORWARD it - // first (F1) — that is a jump past the fleet's own ceiling for us, - // never a consumed epoch, so the D3 rule holds: without it a - // regressed counter makes every entry authored below `Stale` on - // every peer, forever (KNOWN-HAZARDS 7.60). - // [impl->REQ-ROSTER-SELF-LEASE-HEAL] - let lease = { - let mut ep = epochs.lock().unwrap_or_else(|p| p.into_inner()); - heal_self_lease(&store, &provider_hex, &mut ep) - }; - let now = now_secs().to_string(); - let addr = if self_addr.is_null() { - None - } else { - Some(self_addr.clone()) - }; - for s in proven { - store.upsert_self(s, &provider_hex, &label, &machine_id, addr.clone(), &now, lease); - } - let _ = store.save(); - let mut entries = Vec::new(); - let mut tombstones = Vec::new(); - for s in proven { - let (m, t) = store.roster_for(s); - entries.extend(m); - tombstones.extend(t); - } - (entries, tombstones) - }), - sink: Arc::new(move |entries: Vec, tombstones: Vec| { - let mut store = RosterStore::load(); - for e in &entries { - store.merge_entry(e.clone()); - } - for t in &tombstones { - store.tombstone(&t.subnet, &t.pubkey_hex, &t.stamp); - } - let _ = store.save(); - // Roster-merge reconcile (ADR-0039 Decision 3): every learned - // slice re-runs the validated reconcile, so a demoted (suspect) - // route heals from ANY peer's roster — connection-independent - // recovery, not just first-fill. - let path = spt_store::peeraddrs::peer_addrs_file(); - let mut pa = PeerAddrStore::load_from(&path); - let failed = crate::failedaddr::shared() - .lock() - .unwrap_or_else(|p| p.into_inner()); - if reconcile_peeraddrs(&mut pa, &self_hex, &entries, &failed) { - let _ = pa.save_to(&path); - } - }), + provider: Arc::new( + move |proven: &HashSet, self_addr: &serde_json::Value| { + let mut store = RosterStore::load(); + let label = spt_store::hostlabel::os_hostname().unwrap_or_default(); + let machine_id = crate::machineid::machine_id_hash().unwrap_or_default(); + // Peek, never consume: roster propagation must not disturb the + // registry lease counter (the D3 rule). The heal may FAST-FORWARD it + // first (F1) — that is a jump past the fleet's own ceiling for us, + // never a consumed epoch, so the D3 rule holds: without it a + // regressed counter makes every entry authored below `Stale` on + // every peer, forever (KNOWN-HAZARDS 7.60). + // [impl->REQ-ROSTER-SELF-LEASE-HEAL] + let lease = { + let mut ep = epochs.lock().unwrap_or_else(|p| p.into_inner()); + heal_self_lease(&store, &provider_hex, &mut ep) + }; + let now = now_secs().to_string(); + let addr = if self_addr.is_null() { + None + } else { + Some(self_addr.clone()) + }; + for s in proven { + store.upsert_self( + s, + &provider_hex, + &label, + &machine_id, + addr.clone(), + &now, + lease, + ); + } + let _ = store.save(); + let mut entries = Vec::new(); + let mut tombstones = Vec::new(); + for s in proven { + let (m, t) = store.roster_for(s); + entries.extend(m); + tombstones.extend(t); + } + (entries, tombstones) + }, + ), + sink: Arc::new( + move |entries: Vec, tombstones: Vec| { + let mut store = RosterStore::load(); + for e in &entries { + store.merge_entry(e.clone()); + } + for t in &tombstones { + store.tombstone(&t.subnet, &t.pubkey_hex, &t.stamp); + } + let _ = store.save(); + // Roster-merge reconcile (ADR-0039 Decision 3): every learned + // slice re-runs the validated reconcile, so a demoted (suspect) + // route heals from ANY peer's roster — connection-independent + // recovery, not just first-fill. + let path = spt_store::peeraddrs::peer_addrs_file(); + let mut pa = PeerAddrStore::load_from(&path); + let failed = crate::failedaddr::shared() + .lock() + .unwrap_or_else(|p| p.into_inner()); + if reconcile_peeraddrs(&mut pa, &self_hex, &entries, &failed) { + let _ = pa.save_to(&path); + } + }, + ), // Mesh-D7 (REQ-MESH-4): the peer's roster status gates the grace — // tombstoned ⇒ revoked ⇒ denied; listed ⇒ present; otherwise absent. // Re-read per call so a just-propagated tombstone takes effect at once. @@ -1313,14 +1388,22 @@ mod roster_tests { #[test] fn roster_frame_round_trips() { let entries = vec![ - entry("aa", "home", Some(serde_json::json!({"id": "aa", "addrs": ["10.0.0.1:7"]})), 3), + entry( + "aa", + "home", + Some(serde_json::json!({"id": "aa", "addrs": ["10.0.0.1:7"]})), + 3, + ), entry("bb", "home", None, 1), entry("cc", "work", Some(serde_json::json!({"id": "cc"})), 9), ]; let tombstones = vec![tomb("dd", "home")]; let buf = enc_roster(&entries, &tombstones); let (de, dt) = dec_roster(&buf).expect("round-trip"); - assert_eq!(de, entries, "entries (incl. explicit subnet + address) survive"); + assert_eq!( + de, entries, + "entries (incl. explicit subnet + address) survive" + ); assert_eq!(dt, tombstones, "tombstones survive"); } @@ -1371,16 +1454,30 @@ mod roster_tests { let entries = vec![ entry("self", "home", Some(serde_json::json!({"id": "self"})), 1), // skipped entry("cc", "home", Some(addr_c.clone()), 1), // absent ⇒ fill - entry("bb", "home", Some(advertised_b), 1), // present ⇒ keep observed + entry("bb", "home", Some(advertised_b), 1), // present ⇒ keep observed ]; let none = no_failures(); - assert!(reconcile_peeraddrs(&mut pa, "self", &entries, &none), "C was filled"); - assert_eq!(pa.get("cc"), Some(&addr_c), "absent member filled from roster"); - assert_eq!(pa.get("bb"), Some(&observed_b), "observed addr not clobbered"); + assert!( + reconcile_peeraddrs(&mut pa, "self", &entries, &none), + "C was filled" + ); + assert_eq!( + pa.get("cc"), + Some(&addr_c), + "absent member filled from roster" + ); + assert_eq!( + pa.get("bb"), + Some(&observed_b), + "observed addr not clobbered" + ); assert_eq!(pa.get("self"), None, "own entry skipped"); // Idempotent: a second pass with the same input changes nothing. - assert!(!reconcile_peeraddrs(&mut pa, "self", &entries, &none), "no further change"); + assert!( + !reconcile_peeraddrs(&mut pa, "self", &entries, &none), + "no further change" + ); } // [unit->REQ-PEER-ROUTE-CHAIN] [unit->REQ-RECONCILE-FAILED-ADDR-REFUSE] @@ -1411,7 +1508,11 @@ mod roster_tests { "a roster address DIFFERING from the failed one still replaces" ); assert!(!pa.is_suspect("bb"), "suspect mark cleared"); - assert_eq!(pa.valid_route("bb"), Some(&rostered), "route restored from roster"); + assert_eq!( + pa.valid_route("bb"), + Some(&rostered), + "route restored from roster" + ); } // [unit->REQ-RECONCILE-FAILED-ADDR-REFUSE] the livelock, in one function: the @@ -1435,7 +1536,10 @@ mod roster_tests { !reconcile_peeraddrs(&mut pa, "self", &entries, &failed), "nothing changed: the just-failed address is not a repair" ); - assert!(pa.is_suspect("bb"), "the demotion stands — the mark is NOT cleared"); + assert!( + pa.is_suspect("bb"), + "the demotion stands — the mark is NOT cleared" + ); assert!( pa.valid_route("bb").is_none(), "a suspect row is still no route, so the chain falls through to discovery" @@ -1451,9 +1555,20 @@ mod roster_tests { // Refusal: entry for "cc" advertising an address claiming "zz". let mut pa = PeerAddrStore::default(); let none = no_failures(); - let wrong = vec![entry("cc", "home", Some(serde_json::json!({"id": "zz"})), 1)]; - assert!(!reconcile_peeraddrs(&mut pa, "self", &wrong, &none), "mismatch refused"); - assert!(pa.get("cc").is_none(), "nothing seeded from the poison entry"); + let wrong = vec![entry( + "cc", + "home", + Some(serde_json::json!({"id": "zz"})), + 1, + )]; + assert!( + !reconcile_peeraddrs(&mut pa, "self", &wrong, &none), + "mismatch refused" + ); + assert!( + pa.get("cc").is_none(), + "nothing seeded from the poison entry" + ); // Repair: a historical poison row under cc's key is replaced by the // validated roster address. @@ -1463,7 +1578,10 @@ mod roster_tests { ); let good = serde_json::json!({"id": "cc", "addrs": ["10.0.0.3:7"]}); let entries = vec![entry("cc", "home", Some(good.clone()), 1)]; - assert!(reconcile_peeraddrs(&mut pa, "self", &entries, &none), "invalid row repaired"); + assert!( + reconcile_peeraddrs(&mut pa, "self", &entries, &none), + "invalid row repaired" + ); assert_eq!(pa.valid_route("cc"), Some(&good), "repaired row routes"); } } @@ -1484,13 +1602,33 @@ mod grace_tests { // exact-epoch (matched_current = true) assert_eq!(grade_subnet(true, false, Some(Present)), Full); - assert_eq!(grade_subnet(true, false, Some(Absent)), Full, "unknown member, current seed ⇒ admit"); - assert_eq!(grade_subnet(true, false, Some(Tombstoned)), Denied, "revokee denied even exact"); + assert_eq!( + grade_subnet(true, false, Some(Absent)), + Full, + "unknown member, current seed ⇒ admit" + ); + assert_eq!( + grade_subnet(true, false, Some(Tombstoned)), + Denied, + "revokee denied even exact" + ); // prior-epoch only (matched_prev = true, matched_current = false) - assert_eq!(grade_subnet(false, true, Some(Present)), ReseedOnly, "benign offliner ⇒ grace"); - assert_eq!(grade_subnet(false, true, Some(Tombstoned)), Denied, "revoked N-1 ⇒ denied"); - assert_eq!(grade_subnet(false, true, Some(Absent)), Denied, "off-roster N-1 ⇒ never re-seeded"); + assert_eq!( + grade_subnet(false, true, Some(Present)), + ReseedOnly, + "benign offliner ⇒ grace" + ); + assert_eq!( + grade_subnet(false, true, Some(Tombstoned)), + Denied, + "revoked N-1 ⇒ denied" + ); + assert_eq!( + grade_subnet(false, true, Some(Absent)), + Denied, + "off-roster N-1 ⇒ never re-seeded" + ); // ≥2 stale / forged (no match at any held generation) assert_eq!(grade_subnet(false, false, Some(Present)), Denied); @@ -1513,7 +1651,11 @@ mod grace_tests { ]; let buf = enc_seedxfer(&items); assert_eq!(dec_seedxfer(&buf), Some(items.clone()), "round-trip"); - assert_eq!(dec_seedxfer(&enc_seedxfer(&[])), Some(vec![]), "empty round-trip"); + assert_eq!( + dec_seedxfer(&enc_seedxfer(&[])), + Some(vec![]), + "empty round-trip" + ); assert_eq!(dec_seedxfer(&[]), None, "empty buffer (no count)"); assert_eq!(dec_seedxfer(&[0, 0, 0, 1]), None, "count claims 1, no item"); @@ -1546,7 +1688,10 @@ mod grace_tests { // ...but it IS present in the confidential transfer leg (proving that is // the only channel it travels). let xfer = enc_seedxfer(&[("home".to_string(), seed.clone(), 2)]); - assert!(contains_subslice(&xfer, &seed), "the seed rides the transfer leg"); + assert!( + contains_subslice(&xfer, &seed), + "the seed rides the transfer leg" + ); } fn contains_subslice(hay: &[u8], needle: &[u8]) -> bool { diff --git a/crates/spt-daemon/src/serveprobe.rs b/crates/spt-daemon/src/serveprobe.rs index a3c555a4..f0ef60e9 100644 --- a/crates/spt-daemon/src/serveprobe.rs +++ b/crates/spt-daemon/src/serveprobe.rs @@ -67,10 +67,7 @@ pub enum ServeProbeServeOutcome { /// request runs. No gate (module docs): the answer is public serve-state, the /// QUIC handshake is the only subject that matters. // [impl->REQ-SUBNET-5] -pub fn serve_subnet_probe( - brain: &mut Brain, - stream_id: u64, -) -> io::Result { +pub fn serve_subnet_probe(brain: &mut Brain, stream_id: u64) -> io::Result { brain.net_stream_subscribe(stream_id, 0)?; let mut decoder = ServeProbeDecoder::new(); loop { @@ -160,7 +157,9 @@ mod tests { // Join (create) the subnet → attached by default → serving. let mut store = SubnetStore::load(); - store.create_subnet("ACCEPT", spt_store::access::Mode::Open).expect("create"); + store + .create_subnet("ACCEPT", spt_store::access::Mode::Open) + .expect("create"); store.save().expect("save subnet"); assert!(is_serving_subnet("ACCEPT"), "member + attached serves"); diff --git a/crates/spt-daemon/src/service.rs b/crates/spt-daemon/src/service.rs index f2d57b8e..40f9a397 100644 --- a/crates/spt-daemon/src/service.rs +++ b/crates/spt-daemon/src/service.rs @@ -428,7 +428,10 @@ mod tests { None => std::env::remove_var("SPT_HOME"), } assert!(!overridden, "SPT_HOME set ⇒ not the service's home"); - assert!(default, "no SPT_HOME ⇒ the default home the service manages"); + assert!( + default, + "no SPT_HOME ⇒ the default home the service manages" + ); } // [unit->REQ-DAEMON-6] the systemd unit path is the install.sh target: @@ -442,11 +445,15 @@ mod tests { ); assert_eq!( systemd_unit_path_from(None, Some("/home/u")), - Some(PathBuf::from("/home/u/.config/systemd/user/spt-daemon.service")) + Some(PathBuf::from( + "/home/u/.config/systemd/user/spt-daemon.service" + )) ); assert_eq!( systemd_unit_path_from(Some(""), Some("/home/u")), - Some(PathBuf::from("/home/u/.config/systemd/user/spt-daemon.service")) + Some(PathBuf::from( + "/home/u/.config/systemd/user/spt-daemon.service" + )) ); assert_eq!(systemd_unit_path_from(None, None), None); } diff --git a/crates/spt-daemon/src/servicehost.rs b/crates/spt-daemon/src/servicehost.rs index a3586994..cf5cc8bd 100644 --- a/crates/spt-daemon/src/servicehost.rs +++ b/crates/spt-daemon/src/servicehost.rs @@ -472,10 +472,7 @@ pub fn fill_service_command( ) -> Result, String> { let keys = std::collections::BTreeMap::from([ ("adapter_name".to_string(), adapter_name.to_string()), - ( - "adapter_dir".to_string(), - install_dir.display().to_string(), - ), + ("adapter_dir".to_string(), install_dir.display().to_string()), ]); // [impl->REQ-HAZARD-TEMPLATE-ARGV-FILL] tokenize-template-then-fill-each: a // multi-word/quote/semicolon {key} value is exactly one argv element. @@ -605,7 +602,10 @@ impl OrphanSweep { /// previous instance is PROVEN gone (or provably never was): an unresolved /// sweep blocks the spawn rather than risking two live instances. pub fn clear_to_spawn(&self) -> bool { - matches!(self, Self::NoRecord | Self::AlreadyDead | Self::Killed | Self::NotOurs(_)) + matches!( + self, + Self::NoRecord | Self::AlreadyDead | Self::Killed | Self::NotOurs(_) + ) } } @@ -661,7 +661,9 @@ pub fn kill_orphan_service_at(service_dir: &Path, option: &str) -> OrphanSweep { ); OrphanSweep::KillFailed(pid) } else { - spt_proto::emit_line_err!("SERVICE_ORPHAN_REAPED:{option}: pid {pid} (path-verified)"); + spt_proto::emit_line_err!( + "SERVICE_ORPHAN_REAPED:{option}: pid {pid} (path-verified)" + ); OrphanSweep::Killed } } @@ -766,24 +768,23 @@ pub fn supervisor_run( // Each run gets a clean sheet: a fault must be explained by THIS run's // output, never by a previous one's still sitting in the file. reclaim_capture(&capture); - let mut child = - match crate::daemon::detached_no_inherit_env( - program, - args, - &env, - SERVICE_ENV_SCRUB, - Some(&capture), - ) { - Ok(c) => c, - Err(e) => { - let e = format!("spawn {program}: {e}"); - spt_proto::emit_line_err!("SERVICE_STARTUP_FAULT:{option}: {e}"); - return Some(StandDown { - latch: Latch::StartupFault, - detail: Some(e), - }); - } - }; + let mut child = match crate::daemon::detached_no_inherit_env( + program, + args, + &env, + SERVICE_ENV_SCRUB, + Some(&capture), + ) { + Ok(c) => c, + Err(e) => { + let e = format!("spawn {program}: {e}"); + spt_proto::emit_line_err!("SERVICE_STARTUP_FAULT:{option}: {e}"); + return Some(StandDown { + latch: Latch::StartupFault, + detail: Some(e), + }); + } + }; // Park the kill handle BEFORE the wait: a daemon that dies mid-run must // leave its successor something path-verifiable to reap. let image = spt_store::proc::exe_path(child.pid()); @@ -857,7 +858,9 @@ pub fn supervisor_run( // expected-exit special case and no counter is touched here. The // supervisor stands down; the hold-release reconcile starts the NEW // bits. - spt_proto::emit_line_err!("SERVICE_QUIESCED:{option}: cooperative exit (code {code}) under hold"); + spt_proto::emit_line_err!( + "SERVICE_QUIESCED:{option}: cooperative exit (code {code}) under hold" + ); return None; } match on_exit(params, &mut counters, uptime_ms) { @@ -865,7 +868,8 @@ pub fn supervisor_run( spt_proto::emit_line_err!( "SERVICE_EXIT:{option}: code {code} after {uptime_ms}ms \ (crash {}/{}, relaunch in {delay_ms}ms)", - counters.crashes, params.give_up_after + counters.crashes, + params.give_up_after ); // Sleep in slices so a stop lands promptly. let mut left = delay_ms; @@ -1027,9 +1031,7 @@ impl ServiceSet { /// The latch currently suppressing this option, [`Latch::None`] if none. // [impl->REQ-RESIDENT-SERVICE] pub fn latch(&self, option: &str) -> Latch { - self.stand_down(option) - .map(|s| s.latch) - .unwrap_or_default() + self.stand_down(option).map(|s| s.latch).unwrap_or_default() } /// The whole stand-down record — the latch AND the evidence for it. This is @@ -1073,8 +1075,7 @@ impl ServiceSet { pub fn is_held(&self, option: &str) -> bool { let key = spt_store::perch::encode_adapter_option(option); let map = self.holds.lock().unwrap_or_else(|p| p.into_inner()); - map.get(&key) - .is_some_and(|f| f.load(Ordering::SeqCst)) + map.get(&key).is_some_and(|f| f.load(Ordering::SeqCst)) } /// Engage the hold. Step 1 of [`quiesce_order`], and it must land BEFORE the @@ -1272,7 +1273,9 @@ pub fn reconcile_once( }) .is_some_and(|m| m.service.is_some()); if !still_declared { - spt_proto::emit_line_err!("SERVICE_STOPPING:{option}: no active adapter declares it any longer"); + spt_proto::emit_line_err!( + "SERVICE_STOPPING:{option}: no active adapter declares it any longer" + ); set.stop_service(&option); } } @@ -1289,7 +1292,8 @@ pub fn reconcile_once( // Resolve through the OPTION seam even for a bare name, so this path is // option-general by construction rather than adapter-only with an // option-shaped signature bolted on later. - let Ok(manifest) = spt_runtime::registry::resolve_option_in(registered, adapters_dir, &option) + let Ok(manifest) = + spt_runtime::registry::resolve_option_in(registered, adapters_dir, &option) else { continue; // unresolvable manifest: not a service question }; @@ -1318,9 +1322,7 @@ pub fn reconcile_once( // and the operator asking "why will my service not start" would get the // fault's name and nothing else. let mut detail = match decision.outcome { - ServiceOutcome::StartupFault | ServiceOutcome::Latched => { - stood.and_then(|s| s.detail) - } + ServiceOutcome::StartupFault | ServiceOutcome::Latched => stood.and_then(|s| s.detail), _ => None, }; let outcome = match decision.outcome { @@ -1463,7 +1465,9 @@ pub fn quiesce_for_update(set: &ServiceSet, option: &str, service: &Service) -> if let Err(e) = std::fs::write(&marker, b"") { // A marker we could not place is a cooperative exit we will never get; // say so rather than silently spending the grace window on nothing. - spt_proto::emit_line_err!("SERVICE_STOP_MARKER_FAIL:{option}: {e} — falling through to the deadline"); + spt_proto::emit_line_err!( + "SERVICE_STOP_MARKER_FAIL:{option}: {e} — falling through to the deadline" + ); } // 3. AwaitGrace — the kernel-observed exit IS the acknowledgement, so what we // wait on is supervision ending, not any record the service writes. @@ -1855,7 +1859,9 @@ fn handle_service_conn(mut conn: C, set: &ServiceSet) -> io::Re // wedge a newer CLI instead of failing it. Closing the connection // turns that into a prompt, honest error the caller can report. other => { - spt_proto::emit_line_err!("SERVICE_CONTROL_UNKNOWN_OP:{other} — closing the connection"); + spt_proto::emit_line_err!( + "SERVICE_CONTROL_UNKNOWN_OP:{other} — closing the connection" + ); return Ok(()); } } @@ -2311,7 +2317,8 @@ mod tests { }; std::fs::write(dir.join(shipped), b"").unwrap(); - let tokens = fill_service_command("cc", dir, &svc("svcbin --serve {adapter_name}")).unwrap(); + let tokens = + fill_service_command("cc", dir, &svc("svcbin --serve {adapter_name}")).unwrap(); assert_eq!( tokens[0], dir.join(shipped).display().to_string(), @@ -2351,7 +2358,10 @@ mod tests { let home = Path::new("/spt-home"); let a_dir = spt_store::perch::resolve_service_dir_in(home, "cc:dev"); let b_dir = spt_store::perch::resolve_service_dir_in(home, "cc_dev"); - assert_ne!(a_dir, b_dir, "the collision-adversarial pair must stay apart"); + assert_ne!( + a_dir, b_dir, + "the collision-adversarial pair must stay apart" + ); let env = service_env_at(home, "cc:dev", &a_dir); assert_eq!( @@ -2499,13 +2509,16 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); let tokens: Vec = long_running().split(' ').map(String::from).collect(); let (program, args) = tokens.split_first().unwrap(); - let child = - crate::daemon::detached_no_inherit_env(program, args, &[], &[], None).expect("spawn orphan"); + let child = crate::daemon::detached_no_inherit_env(program, args, &[], &[], None) + .expect("spawn orphan"); let pid = child.pid(); // Park exactly what a supervisor parks, then FORGET the handle — this is // a dead daemon's orphan, which nobody holds a handle to. let image = spt_store::proc::exe_path(pid); - assert!(image.is_some(), "the image oracle must answer for our own child"); + assert!( + image.is_some(), + "the image oracle must answer for our own child" + ); park_identity(tmp.path(), pid, image.as_deref()); drop(child); @@ -2539,7 +2552,10 @@ mod tests { #[test] fn empty_and_dead_orphan_records_read_apart() { let tmp = tempfile::tempdir().unwrap(); - assert_eq!(kill_orphan_service_at(tmp.path(), "cc"), OrphanSweep::NoRecord); + assert_eq!( + kill_orphan_service_at(tmp.path(), "cc"), + OrphanSweep::NoRecord + ); park_identity(tmp.path(), 0, None); assert_eq!( kill_orphan_service_at(tmp.path(), "cc"), @@ -2707,9 +2723,8 @@ mod tests { }) }; assert!( - wait_until(|| read_parked_identity(&dir).is_some_and(|(pid, _)| { - pid != 0 && spt_store::proc::is_process_alive(pid) - })), + wait_until(|| read_parked_identity(&dir) + .is_some_and(|(pid, _)| { pid != 0 && spt_store::proc::is_process_alive(pid) })), "the supervised child never came up" ); let pid = read_parked_identity(&dir).unwrap().0; @@ -2928,11 +2943,25 @@ mod tests { let set = ServiceSet::new(); let params = ServiceParams::default(); - let out = reconcile_once(&adapters, ®istered, &set, Opportunity::Boot, None, ¶ms); - assert_eq!(out.len(), 1, "one candidate per registered adapter: {out:?}"); + let out = reconcile_once( + &adapters, + ®istered, + &set, + Opportunity::Boot, + None, + ¶ms, + ); + assert_eq!( + out.len(), + 1, + "one candidate per registered adapter: {out:?}" + ); assert_eq!(out[0].option, "a", "the RAW option is what is reported"); assert_eq!(out[0].outcome, ServiceOutcome::Started); - assert_eq!(out[0].detail, None, "a plain Started invents no reassurance"); + assert_eq!( + out[0].detail, None, + "a plain Started invents no reassurance" + ); assert!(set.contains("a")); let dir = spt_store::perch::resolve_service_dir("a"); @@ -2942,8 +2971,14 @@ mod tests { ); let first = read_parked_identity(&dir).expect("parked").0; - let again = - reconcile_once(&adapters, ®istered, &set, Opportunity::Boot, None, ¶ms); + let again = reconcile_once( + &adapters, + ®istered, + &set, + Opportunity::Boot, + None, + ¶ms, + ); assert_eq!(again[0].outcome, ServiceOutcome::AlreadyRunning); assert_eq!(set.len(), 1, "one supervisor per option"); assert_eq!( @@ -2973,14 +3008,28 @@ mod tests { let set = ServiceSet::new(); let params = ServiceParams::default(); - let out = reconcile_once(&adapters, ®istered, &set, Opportunity::Boot, None, ¶ms); + let out = reconcile_once( + &adapters, + ®istered, + &set, + Opportunity::Boot, + None, + ¶ms, + ); assert_eq!(out[0].outcome, ServiceOutcome::BindDeferred); assert!( set.is_empty(), "a deferred service is reported, never supervised" ); - let out = reconcile_once(&adapters, ®istered, &set, Opportunity::Bind, None, ¶ms); + let out = reconcile_once( + &adapters, + ®istered, + &set, + Opportunity::Bind, + None, + ¶ms, + ); assert_eq!(out[0].outcome, ServiceOutcome::Started); assert!(set.contains("a")); @@ -3010,7 +3059,14 @@ mod tests { let set = ServiceSet::new(); let params = fast_latch_params(); - let out = reconcile_once(&adapters, ®istered, &set, Opportunity::Boot, None, ¶ms); + let out = reconcile_once( + &adapters, + ®istered, + &set, + Opportunity::Boot, + None, + ¶ms, + ); assert_eq!(out[0].outcome, ServiceOutcome::Started); assert!( @@ -3025,7 +3081,14 @@ mod tests { ); // A NON-clearing opportunity: report the suppression, raise nothing. - let out = reconcile_once(&adapters, ®istered, &set, Opportunity::Bind, None, ¶ms); + let out = reconcile_once( + &adapters, + ®istered, + &set, + Opportunity::Bind, + None, + ¶ms, + ); assert_eq!(out[0].outcome, ServiceOutcome::StartupFault); assert_eq!( out[0].detail, None, @@ -3291,7 +3354,14 @@ mod tests { assert!(!set.contains("a")); // THE ASSERTION: a clearing opportunity does not start a held option. - let out = reconcile_once(&adapters, ®istered, &set, Opportunity::Boot, None, ¶ms); + let out = reconcile_once( + &adapters, + ®istered, + &set, + Opportunity::Boot, + None, + ¶ms, + ); assert_eq!( out.iter().map(|o| o.outcome).collect::>(), [ServiceOutcome::Held], @@ -3777,7 +3847,14 @@ mod tests { )]; let set = ServiceSet::new(); let params = fast_latch_params(); - reconcile_once(&adapters, ®istered, &set, Opportunity::Boot, None, ¶ms); + reconcile_once( + &adapters, + ®istered, + &set, + Opportunity::Boot, + None, + ¶ms, + ); assert!( wait_until(|| set.latch("a") == Latch::StartupFault), "the fixture never latched" @@ -3838,8 +3915,18 @@ mod tests { crate::test_home::with_home(|home| { let (adapters, install) = sweep_dirs(home); let registered = vec![ - reg("a", &install, true, Some((long_running(), ServiceStart::Boot))), - reg("b", &install, false, Some((long_running(), ServiceStart::Bind))), + reg( + "a", + &install, + true, + Some((long_running(), ServiceStart::Boot)), + ), + reg( + "b", + &install, + false, + Some((long_running(), ServiceStart::Bind)), + ), reg("c", &install, true, None), ]; let set = ServiceSet::new(); diff --git a/crates/spt-daemon/src/shellchan.rs b/crates/spt-daemon/src/shellchan.rs index 78956709..2e952606 100644 --- a/crates/spt-daemon/src/shellchan.rs +++ b/crates/spt-daemon/src/shellchan.rs @@ -30,15 +30,15 @@ use std::path::Path; use spt_proto::event::{ compose_typed_event, EVENT_TYPE_ACTIVITY, EVENT_TYPE_ATTACH, EVENT_TYPE_BOUNDARY, - EVENT_TYPE_DRIVE, EVENT_TYPE_IO, EVENT_TYPE_SENSORY, - EVENT_TYPE_SHELL_CLOSE, EVENT_TYPE_SHELL_COMMAND, EVENT_TYPE_SHELL_FILE, EVENT_TYPE_SHELL_TEXT, + EVENT_TYPE_DRIVE, EVENT_TYPE_IO, EVENT_TYPE_SENSORY, EVENT_TYPE_SHELL_CLOSE, + EVENT_TYPE_SHELL_COMMAND, EVENT_TYPE_SHELL_FILE, EVENT_TYPE_SHELL_TEXT, }; use spt_runtime::manifest::Shell; use spt_net::net::attach::AttachIntent; use crate::brain::{now_ms, Brain, BrokerEvent}; -use crate::effect::{Minter, MintedOp}; +use crate::effect::{MintedOp, Minter}; use crate::shellhost::{self, frame_mac, verify_frame_mac}; /// The broker session label for a stdin-hosted shell instance — path-shaped so @@ -561,7 +561,11 @@ mod tests { spt_store::spool::spool_message_at(perch, "", &stamp_frame(&new, &frame_new)).unwrap(); spt_store::spool::spool_message_at(perch, "", "garbage no-mac row").unwrap(); - assert_eq!(restamp_pending_at(perch, &old, &new), 1, "only the old-key row"); + assert_eq!( + restamp_pending_at(perch, &old, &new), + 1, + "only the old-key row" + ); let bodies: Vec = spt_store::spool::peek_all_at(perch) .unwrap() .into_iter() @@ -578,7 +582,11 @@ mod tests { "already-new row untouched" ); assert_eq!(bodies[2], "garbage no-mac row", "foreign row untouched"); - assert_eq!(restamp_pending_at(perch, &old, &new), 0, "idempotent — second walk is a no-op"); + assert_eq!( + restamp_pending_at(perch, &old, &new), + 0, + "idempotent — second walk is a no-op" + ); // The drain-time second chance: a straggler stamped under the retired // stash re-stamps at delivery; current-key and foreign bodies pass through. @@ -594,7 +602,11 @@ mod tests { "straggler re-stamps at drain" ); let current = stamp_frame(&new, &frame_new); - assert_eq!(restamp_for_drain(perch, &new, ¤t), current, "current passes through"); + assert_eq!( + restamp_for_drain(perch, &new, ¤t), + current, + "current passes through" + ); assert_eq!( restamp_for_drain(perch, &new, "garbage no-mac row"), "garbage no-mac row", @@ -703,7 +715,10 @@ mod tests { Some(1_753_372_800_123), "since decodes as epoch ms (the value edge arithmetic anchors to)" ); - assert!(ev.body.is_empty(), "the body is empty and reserved: {frame}"); + assert!( + ev.body.is_empty(), + "the body is empty and reserved: {frame}" + ); // Attr ORDER is part of the published shape. assert_eq!( ev.attrs.iter().map(|(k, _)| k.as_str()).collect::>(), diff --git a/crates/spt-daemon/src/shellhost.rs b/crates/spt-daemon/src/shellhost.rs index 593c6f68..25d9a503 100644 --- a/crates/spt-daemon/src/shellhost.rs +++ b/crates/spt-daemon/src/shellhost.rs @@ -194,7 +194,10 @@ fn fill_spawn_command( // token snapshot (the D-2 stale-snapshot class). // [impl->REQ-HAZARD-SHELL-STALE-ONLINE] let new_key = link_key(&token); - for old in [&parked_before_mint, &retired_before_mint].into_iter().flatten() { + for old in [&parked_before_mint, &retired_before_mint] + .into_iter() + .flatten() + { crate::shellchan::restamp_pending_at(&perch, &link_key(old), &new_key); } // Stash the just-rotated-out token for the drain's second chance; a @@ -230,8 +233,8 @@ fn fill_spawn_command( }; // [impl->REQ-HAZARD-TEMPLATE-ARGV-FILL] tokenize-template-then-fill-each: a // multi-word/quote/semicolon {key} value is exactly one argv element. - let mut tokens = - spt_runtime::runtime::fill_template_tokens(&shell.spawn, &keys).map_err(|e| e.to_string())?; + let mut tokens = spt_runtime::runtime::fill_template_tokens(&shell.spawn, &keys) + .map_err(|e| e.to_string())?; let Some(program) = tokens.first_mut() else { return Err("empty spawn command".into()); }; @@ -870,10 +873,7 @@ pub fn close_shell( // [impl->REQ-HAZARD-SHELL-STALE-ONLINE] // (remove-then-rename: Windows rename refuses an existing destination.) let _ = std::fs::remove_file(perch.join(RETIRED_TOKEN_FILE)); - let _ = std::fs::rename( - perch.join(LINK_TOKEN_FILE), - perch.join(RETIRED_TOKEN_FILE), - ); + let _ = std::fs::rename(perch.join(LINK_TOKEN_FILE), perch.join(RETIRED_TOKEN_FILE)); // Clear any pending drive frame (M11-W2, REQ-SHELL-3): the link credential // is now retired, so a relink will mint a fresh token — but eagerly evict the @@ -1097,7 +1097,10 @@ mod tests { #[test] fn a_post_ack_silence_is_indeterminate_not_failure() { let (out, spawned_here) = route(Err(LaunchRouteError::Indeterminate("hung up".into()))); - assert!(!spawned_here, "an unknown outcome must never be re-attempted"); + assert!( + !spawned_here, + "an unknown outcome must never be re-attempted" + ); let err = out.expect_err("silence after the ack is not a success"); assert!( err.is_indeterminate(), @@ -1245,7 +1248,10 @@ mod tests { e.fallback_allowed(), "nothing was spawned, so the caller keeps its in-process path: {e}" ); - assert!(!e.is_indeterminate(), "an unreached daemon launched nothing"); + assert!( + !e.is_indeterminate(), + "an unreached daemon launched nothing" + ); } // [unit->REQ-EP-6] a GATEWAY-typed owner spawns + owns a shell identically @@ -1376,7 +1382,9 @@ mod tests { let owlery = tmp.path().join("owl space"); // spaces: the argv-fill hazard shape std::fs::create_dir_all(&owlery).unwrap(); let id = spawn_record(&owlery, "doyle", "mock-shell", None).unwrap(); - let shell = shell_section(&format!("{NOOP} --root {{perch_dir}} --link {{link_token}}")); + let shell = shell_section(&format!( + "{NOOP} --root {{perch_dir}} --link {{link_token}}" + )); let tokens = fill_spawn_command(&owlery, "doyle", &id, "mock-shell", None, &shell) .expect("perch_dir is a spawn substitution key"); let perch = spt_store::perch::resolve_shell_perch_path_in(&owlery, "doyle", &id); @@ -1407,7 +1415,11 @@ mod tests { // token — the release shape, and the argv-fill hazard shape at once. let install = tmp.path().join("adapter dir"); std::fs::create_dir_all(&install).unwrap(); - let shipped = if cfg!(windows) { "runner.exe" } else { "runner" }; + let shipped = if cfg!(windows) { + "runner.exe" + } else { + "runner" + }; std::fs::write(install.join(shipped), b"").unwrap(); let id = spawn_record(&owlery, "doyle", "mock-shell", None).unwrap(); diff --git a/crates/spt-daemon/src/shellwake.rs b/crates/spt-daemon/src/shellwake.rs index 7caf020f..ea3706e8 100644 --- a/crates/spt-daemon/src/shellwake.rs +++ b/crates/spt-daemon/src/shellwake.rs @@ -480,7 +480,12 @@ fn forward_wake(owner: &str, node: &str) -> Result { // The wake-forward rest op's seq source is a fresh `now_ms()` — its OWN // minting source, distinct from shellchan's spool-row counter (doyle ruling: // the tag names the seq source, not the subsystem), so it stamps `wake`. - || Ok(crate::effect::MintedOp::new(crate::effect::Minter::Wake, now_ms())), + || { + Ok(crate::effect::MintedOp::new( + crate::effect::Minter::Wake, + now_ms(), + )) + }, |op| { let conn = brain.net_dial(addr.clone(), None)?; // Keep the tracing string's seq consistent with the (possibly re-minted) op. @@ -569,8 +574,8 @@ fn fill_wake_command( } // [impl->REQ-HAZARD-TEMPLATE-ARGV-FILL] tokenize-template-then-fill-each: a // multi-word/quote/semicolon {key} value is exactly one argv element. - let mut tokens = - spt_runtime::runtime::fill_template_tokens(wake_command, &keys).map_err(|e| e.to_string())?; + let mut tokens = spt_runtime::runtime::fill_template_tokens(wake_command, &keys) + .map_err(|e| e.to_string())?; let Some(program) = tokens.first_mut() else { return Err("empty wake_command".into()); }; @@ -627,7 +632,9 @@ fn heal_stale_online_records(owlery: &Path) { let mut healed = info.clone(); healed.status = truth.to_string(); if shellinfo::write_shell_info(&perch, &healed).is_ok() { - spt_proto::emit_line_err!("SHELL_RECORD_HEALED:{owner}/{shell_id}: online -> {truth}"); + spt_proto::emit_line_err!( + "SHELL_RECORD_HEALED:{owner}/{shell_id}: online -> {truth}" + ); } } } @@ -1445,8 +1452,13 @@ mod tests { std::fs::write(owner_dir.join("info.json"), "{}").unwrap(); let set = Arc::new(WakeSet::new()); - let restored = - restore_persistent_shells_on_owner_online(owlery, ®istered, &adapters_dir, &mut edge, &set); + let restored = restore_persistent_shells_on_owner_online( + owlery, + ®istered, + &adapters_dir, + &mut edge, + &set, + ); assert!( restored.contains(&format!("ling/{stranded}")), @@ -1463,8 +1475,13 @@ mod tests { // ...and the trigger is an EDGE: the owner stays online, a NEW casualty is // stranded, and the next pass does nothing. A level trigger would take it. let late = mk(boot.saturating_sub(600_000)); - let again = - restore_persistent_shells_on_owner_online(owlery, ®istered, &adapters_dir, &mut edge, &set); + let again = restore_persistent_shells_on_owner_online( + owlery, + ®istered, + &adapters_dir, + &mut edge, + &set, + ); assert!( again.is_empty(), "no NEW owner-online transition ⇒ no restore attempt at all; this is what \ @@ -1494,9 +1511,13 @@ mod tests { let shipped = if cfg!(windows) { "waker.exe" } else { "waker" }; std::fs::write(install.join(shipped), b"").unwrap(); - let tokens = - fill_wake_command("sh-1", "mock-shell", Some(&install), "waker --root {adapter_dir}") - .expect("adapter_dir is a wake substitution key"); + let tokens = fill_wake_command( + "sh-1", + "mock-shell", + Some(&install), + "waker --root {adapter_dir}", + ) + .expect("adapter_dir is a wake substitution key"); assert_eq!( tokens[0], install.join(shipped).display().to_string(), @@ -1878,7 +1899,11 @@ mod tests { // above is the derivation policy, not a broken rig. let off = spawn_record(owlery, "doyle", "mock-wake", None).unwrap(); reconcile_once(owlery, ®istered, &adapters_dir, &set, ¶ms); - assert_eq!(set.len(), 1, "the offline sibling {off} still gets a watcher"); + assert_eq!( + set.len(), + 1, + "the offline sibling {off} still gets a watcher" + ); set.stop_watcher(owlery, "doyle", &off); } @@ -2158,7 +2183,10 @@ mod tests { 1, "only the profiled instance (overlay adds wake_command) gets a watcher" ); - assert!(set.contains("doyle", &pid), "the profiled instance is the one watched"); + assert!( + set.contains("doyle", &pid), + "the profiled instance is the one watched" + ); set.stop_watcher(owlery, "doyle", &pid); } diff --git a/crates/spt-daemon/src/stderrlog.rs b/crates/spt-daemon/src/stderrlog.rs index 3adc7f51..32b46488 100644 --- a/crates/spt-daemon/src/stderrlog.rs +++ b/crates/spt-daemon/src/stderrlog.rs @@ -142,7 +142,10 @@ fn redirect_stderr_to(file: std::fs::File) { pub fn install(role: &str, generation: u64) -> Option { let dir = stderr_log_dir(); if let Err(e) = std::fs::create_dir_all(&dir) { - spt_proto::emit_line_err!("STDERR_PERSIST_SKIP: could not create {}: {e}", dir.display()); + spt_proto::emit_line_err!( + "STDERR_PERSIST_SKIP: could not create {}: {e}", + dir.display() + ); return None; } let path = stderr_log_path(); @@ -151,10 +154,17 @@ pub fn install(role: &str, generation: u64) -> Option { if should_roll(size, STDERR_LOG_CAP) { roll_files(&dir, STDERR_LOG_KEEP); } - let mut file = match std::fs::OpenOptions::new().create(true).append(true).open(&path) { + let mut file = match std::fs::OpenOptions::new() + .create(true) + .append(true) + .open(&path) + { Ok(f) => f, Err(e) => { - spt_proto::emit_line_err!("STDERR_PERSIST_SKIP: could not open {}: {e}", path.display()); + spt_proto::emit_line_err!( + "STDERR_PERSIST_SKIP: could not open {}: {e}", + path.display() + ); return None; } }; @@ -175,9 +185,18 @@ mod tests { #[test] fn should_roll_at_or_over_cap_only() { assert!(!should_roll(0, STDERR_LOG_CAP), "empty never rolls"); - assert!(!should_roll(STDERR_LOG_CAP - 1, STDERR_LOG_CAP), "just under never rolls"); - assert!(should_roll(STDERR_LOG_CAP, STDERR_LOG_CAP), "exactly at cap rolls"); - assert!(should_roll(STDERR_LOG_CAP + 1, STDERR_LOG_CAP), "over cap rolls"); + assert!( + !should_roll(STDERR_LOG_CAP - 1, STDERR_LOG_CAP), + "just under never rolls" + ); + assert!( + should_roll(STDERR_LOG_CAP, STDERR_LOG_CAP), + "exactly at cap rolls" + ); + assert!( + should_roll(STDERR_LOG_CAP + 1, STDERR_LOG_CAP), + "over cap rolls" + ); assert!(!should_roll(u64::MAX, 0), "cap 0 disables rotation"); } @@ -196,14 +215,20 @@ mod tests { roll_files(dir.path(), STDERR_LOG_KEEP); // The old backup is dropped; the current became the new .1. - assert!(!cur.exists(), "current was rolled away (fresh install reopens it)"); + assert!( + !cur.exists(), + "current was rolled away (fresh install reopens it)" + ); assert_eq!( std::fs::read(&bak).unwrap(), b"CURRENT-A", "the current file's content is preserved as the .1 backup" ); // No .2 accumulates (KEEP=2 keeps only current + .1). - assert!(!rolled_path(dir.path(), 2).exists(), "no unbounded accumulation"); + assert!( + !rolled_path(dir.path(), 2).exists(), + "no unbounded accumulation" + ); } // [unit->REQ-DAEMON-STDERR-PERSIST] KEEP<=1 keeps NO backup — the current file is @@ -216,7 +241,10 @@ mod tests { std::fs::write(&cur, b"CURRENT").unwrap(); roll_files(dir.path(), 1); assert!(!cur.exists(), "keep=1 clears the current file"); - assert!(!rolled_path(dir.path(), 1).exists(), "keep=1 makes no backup"); + assert!( + !rolled_path(dir.path(), 1).exists(), + "keep=1 makes no backup" + ); } // [unit->REQ-DAEMON-STDERR-PERSIST] the log path derivation sits under SPT_HOME @@ -226,13 +254,20 @@ mod tests { fn path_under_home_and_stamp_is_legible() { crate::test_home::with_home(|home| { let p = stderr_log_path(); - assert_eq!(p, sink_path(home), "explicit-home helper matches the installed sink"); + assert_eq!( + p, + sink_path(home), + "explicit-home helper matches the installed sink" + ); assert!(p.starts_with(home), "log lives under SPT_HOME: {p:?}"); assert!(p.ends_with(STDERR_LOG_BASENAME)); assert!(p.parent().unwrap().ends_with("logs")); }); let stamp = stamp_line("broker", 7); - assert!(stamp.contains("broker") && stamp.contains("generation 7"), "got {stamp}"); + assert!( + stamp.contains("broker") && stamp.contains("generation 7"), + "got {stamp}" + ); assert!(!stamp.contains("REQ-"), "no internal tag leaks: {stamp}"); } } diff --git a/crates/spt-daemon/src/sync.rs b/crates/spt-daemon/src/sync.rs index b738f477..efe33a03 100644 --- a/crates/spt-daemon/src/sync.rs +++ b/crates/spt-daemon/src/sync.rs @@ -555,7 +555,9 @@ pub fn reconcile_after_sync( // literal, not merely a matter of role conflicts being rare (REQ-EP-7). // [impl->REQ-EP-7] if std::path::Path::new(&file).file_name() - == Some(std::ffi::OsStr::new(spt_store::contextstore::LIVE_ROLE_FILE)) + == Some(std::ffi::OsStr::new( + spt_store::contextstore::LIVE_ROLE_FILE, + )) { outcomes.push((branch, file, ReconcileOutcome::RoleExcluded)); continue; @@ -692,7 +694,10 @@ mod tests { b"\nREMOTE role", ) .unwrap(); - assert_eq!(cs.list_conflicts(&wt, Some("live-role.md")).unwrap().len(), 1); + assert_eq!( + cs.list_conflicts(&wt, Some("live-role.md")).unwrap().len(), + 1 + ); let report = SyncPullReport { applied: vec![ApplyReport { @@ -716,9 +721,8 @@ mod tests { "[adapter]\nname=\"mock\"\nversion=\"1\"\nmin_spt_core_version=\"1\"\n\n\ [session.psyche_resume]\ncommand='{cmd}'\n" ); - let rt = spt_runtime::ManifestRuntime::new( - spt_runtime::Manifest::from_toml_str(&toml).unwrap(), - ); + let rt = + spt_runtime::ManifestRuntime::new(spt_runtime::Manifest::from_toml_str(&toml).unwrap()); let outcomes = reconcile_after_sync( &rt, diff --git a/crates/spt-daemon/src/translation.rs b/crates/spt-daemon/src/translation.rs index 74c46a3b..c092a642 100644 --- a/crates/spt-daemon/src/translation.rs +++ b/crates/spt-daemon/src/translation.rs @@ -113,7 +113,10 @@ pub fn key_to_bytes(key: &str) -> Option> { _ => { // ctrl+: a control byte. `ctrl+s` → 0x13, `ctrl+space` → NUL, // `ctrl+[` → ESC, etc. Only single-char chords are mapped. - if let Some(rest) = lower.strip_prefix("ctrl+").or_else(|| lower.strip_prefix("c-")) { + if let Some(rest) = lower + .strip_prefix("ctrl+") + .or_else(|| lower.strip_prefix("c-")) + { return ctrl_byte(rest).map(|b| vec![b]); } // A single literal character → its own bytes (e.g. `{key:"y"}`). @@ -265,10 +268,7 @@ impl TranslationChild { } let mut child = command.spawn()?; let pid = child.id().into(); - let stdout = child - .stdout - .take() - .expect("stdout piped at spawn"); + let stdout = child.stdout.take().expect("stdout piped at spawn"); let stdin = child.stdin.take().expect("stdin piped at spawn"); let reader = thread::spawn(move || { let buf = BufReader::new(stdout); @@ -416,9 +416,9 @@ mod tests { let (tx, _rx) = std::sync::mpsc::channel::(); match TranslationChild::spawn(&[prog.to_string()], tx) { Ok(child) => child.terminate(), // bounded no-zombie reap - Err(e) => panic!( - "CREATE_NO_WINDOW must not break the spawn (error-87 flag-combo class): {e}" - ), + Err(e) => { + panic!("CREATE_NO_WINDOW must not break the spawn (error-87 flag-combo class): {e}") + } } } @@ -429,11 +429,15 @@ mod tests { fn key_cmd_parses_each_wire_shape() { assert_eq!( serde_json::from_str::(r#"{"key":"ctrl+s"}"#).unwrap(), - KeyCmd::Key { key: "ctrl+s".into() } + KeyCmd::Key { + key: "ctrl+s".into() + } ); assert_eq!( serde_json::from_str::(r#"{"text":"hello"}"#).unwrap(), - KeyCmd::Text { text: "hello".into() } + KeyCmd::Text { + text: "hello".into() + } ); assert_eq!( serde_json::from_str::(r#"{"delay_ms":50}"#).unwrap(), @@ -446,7 +450,9 @@ mod tests { // forward-compat: an unknown field alongside a known shape still parses. assert_eq!( serde_json::from_str::(r#"{"key":"enter","repeat":3}"#).unwrap(), - KeyCmd::Key { key: "enter".into() } + KeyCmd::Key { + key: "enter".into() + } ); // a line matching no shape is an error. assert!(serde_json::from_str::(r#"{"bogus":1}"#).is_err()); @@ -471,14 +477,20 @@ mod tests { // flush step 1 takes the buffered bytes (floor STAYS held) ... assert_eq!(f.take_or_release(), Some(b"hello".to_vec())); - assert!(f.is_held(), "floor stays held mid-flush so order is preserved"); + assert!( + f.is_held(), + "floor stays held mid-flush so order is preserved" + ); // ... input arriving mid-flush keeps buffering ... assert!(f.buffer_if_held(b"!"), "mid-flush input still buffers"); assert_eq!(f.take_or_release(), Some(b"!".to_vec())); // ... and the empty step RELEASES the floor. assert_eq!(f.take_or_release(), None); assert!(!f.is_held(), "drained empty → floor released"); - assert!(!f.buffer_if_held(b"z"), "released floor passes through again"); + assert!( + !f.buffer_if_held(b"z"), + "released floor passes through again" + ); } // [unit->REQ-MSG-IDLE-TRANSLATION-BINARY] the send-keys byte map: named keys, @@ -494,7 +506,7 @@ mod tests { assert_eq!(key_to_bytes("ctrl+s"), Some(vec![0x13])); assert_eq!(key_to_bytes("ctrl+a"), Some(vec![0x01])); assert_eq!(key_to_bytes("ctrl+b"), Some(vec![0x02])); // the rc detach byte - // arrows as xterm CSI. + // arrows as xterm CSI. assert_eq!(key_to_bytes("up"), Some(b"\x1b[A".to_vec())); assert_eq!(key_to_bytes("left"), Some(b"\x1b[D".to_vec())); // a single literal char passes through. diff --git a/crates/spt-daemon/src/tunnelhub.rs b/crates/spt-daemon/src/tunnelhub.rs index 9065deae..32ef567c 100644 --- a/crates/spt-daemon/src/tunnelhub.rs +++ b/crates/spt-daemon/src/tunnelhub.rs @@ -206,7 +206,14 @@ impl TunnelHub { /// `token`. A second open (a relink) replaces the prior entry — the old stream /// ids are no longer referenced under the fresh token. // [impl->REQ-SHELL-4] - pub fn open(&self, owner: &str, shell_id: &str, token: &str, owner_stream: u64, shell_stream: u64) { + pub fn open( + &self, + owner: &str, + shell_id: &str, + token: &str, + owner_stream: u64, + shell_stream: u64, + ) { let mut map = self.map.lock().unwrap(); map.insert( slot_key(owner, shell_id), @@ -270,7 +277,11 @@ impl TunnelHub { /// dispatch change, no brain serve loop). Thread-per-connection (mirroring the /// digest / drive control channels). // [impl->REQ-SHELL-4] -pub fn serve_tunnel_control(name: &str, hub: Arc, broker: Arc) -> io::Result<()> { +pub fn serve_tunnel_control( + name: &str, + hub: Arc, + broker: Arc, +) -> io::Result<()> { let listener = LocalSocketTransport::bind(name)?; loop { let conn = listener.accept()?; @@ -447,8 +458,8 @@ pub fn tunnel_recv(name: &str, stream_id: u64) -> io::Result<(Vec, bool)> { let env = read_frame(&mut conn)?; let res: TunnelRecvResult = serde_json::from_value(env.payload) .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; - let bytes = decode_bytes(&res.data_b64) - .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + let bytes = + decode_bytes(&res.data_b64).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; Ok((bytes, res.finished)) } @@ -535,8 +546,14 @@ mod tests { let hub = TunnelHub::new(); hub.open("doyle", "mock-shell-0", "old-token", 7, 8); hub.open("doyle", "mock-shell-0", "new-token", 11, 12); - assert_eq!(hub.owner_stream("doyle", "mock-shell-0", "new-token"), Some(11)); - assert_eq!(hub.shell_stream("doyle", "mock-shell-0", "new-token"), Some(12)); + assert_eq!( + hub.owner_stream("doyle", "mock-shell-0", "new-token"), + Some(11) + ); + assert_eq!( + hub.shell_stream("doyle", "mock-shell-0", "new-token"), + Some(12) + ); assert_eq!(hub.owner_stream("doyle", "mock-shell-0", "old-token"), None); } diff --git a/crates/spt-daemon/src/wan.rs b/crates/spt-daemon/src/wan.rs index a58a567e..8ee09171 100644 --- a/crates/spt-daemon/src/wan.rs +++ b/crates/spt-daemon/src/wan.rs @@ -387,7 +387,10 @@ pub enum ForkRequestOutcome { Forked, /// The receiver answered, but the fork did not happen — the token and its /// detail, carried verbatim for the operator. - Refused { token: String, detail: Option }, + Refused { + token: String, + detail: Option, + }, /// The stream finished with no reply: an older daemon that dropped the tag, /// or an access refusal. Unconfirmed either way. NoReply, @@ -572,9 +575,7 @@ pub fn request_answer( /// Map one ack to the outcome triple. An unknown token is NOT applied and NOT a /// refusal — it is silence with extra bytes. // [impl->REQ-KNOCK-ANSWER-RECEIPT] -pub fn classify_answer_ack( - reply: &spt_net::net::answermsg::AnswerReply, -) -> AnswerRequestOutcome { +pub fn classify_answer_ack(reply: &spt_net::net::answermsg::AnswerReply) -> AnswerRequestOutcome { use spt_net::net::answermsg::ack; match reply.outcome.as_str() { @@ -591,9 +592,7 @@ pub fn classify_answer_ack( /// than carried: the wire tolerates a receiver that attaches a target to a /// refusal, and this is the seam that refuses to render it. // [impl->REQ-KNOCK-REDEEM-WIRE] -pub fn classify_redeem_reply( - reply: spt_net::net::redeemmsg::RedeemReply, -) -> RedeemRequestOutcome { +pub fn classify_redeem_reply(reply: spt_net::net::redeemmsg::RedeemReply) -> RedeemRequestOutcome { use spt_net::net::redeemmsg::token; if reply.outcome == token::REDEEMED { @@ -791,7 +790,11 @@ fn owed_trust_warning( // [impl->REQ-TRUST-WARNING-OVERRIDE] let custom = spt_store::trustwarn::override_for(&msg.target); let body = compose_trust_warning(&peer, custom.as_deref()); - Some(OwedWarning { session: bound_session, peer, body }) + Some(OwedWarning { + session: bound_session, + peer, + body, + }) } /// Deliver an owed warning as its OWN system-authored message — the fail-safe @@ -940,7 +943,6 @@ pub fn receive_wan( ); } - if !perch_exists(&msg.target) { return WanOutcome::NoPerch; } @@ -1061,9 +1063,13 @@ fn deliver_admitted( // broker's dispatch_endpoint_input). // [impl->REQ-WAN-SPT-HOSTED-DELIVERY] // [impl->REQ-HAZARD-DELIVERY-STARVATION] - if let Some((true, _)) = - crate::inject::try_spt_hosted_inject(&msg.target, delivered_from, delivered_body, owlery, false) - { + if let Some((true, _)) = crate::inject::try_spt_hosted_inject( + &msg.target, + delivered_from, + delivered_body, + owlery, + false, + ) { let _ = spool::wan_mark_seen_at(perch_path, &msg.op_id); return WanOutcome::DeliveredInject; } @@ -1252,11 +1258,17 @@ mod tests { // Empty from → the origin node's display (node_label_display(origin, None)) — // never blank, and it identifies the QUIC-proven origin node. let rendered = render_delivered_from("", origin); - assert!(!rendered.is_empty(), "an empty from must NEVER render blank"); + assert!( + !rendered.is_empty(), + "an empty from must NEVER render blank" + ); assert_eq!(rendered, node_label_display(origin, None)); // A non-empty from is untouched (the identity gate + reply routing keep it). assert_eq!(render_delivered_from("peer-x", origin), "peer-x"); - assert_eq!(render_delivered_from("cli@ENLYZEAM", origin), "cli@ENLYZEAM"); + assert_eq!( + render_delivered_from("cli@ENLYZEAM", origin), + "cli@ENLYZEAM" + ); } // [unit->REQ-WAN-SEND-DELIVERY] the reply-leg token vocabulary round-trips: @@ -1285,7 +1297,10 @@ mod tests { WanRequestOutcome::from_token("some_future_verb"), WanRequestOutcome::NoReply ); - assert_eq!(WanRequestOutcome::from_token(""), WanRequestOutcome::NoReply); + assert_eq!( + WanRequestOutcome::from_token(""), + WanRequestOutcome::NoReply + ); } // [unit->REQ-MSG-5] WAN-ingress re-stamp (KH 7.5): a user-msg body from an @@ -1345,18 +1360,30 @@ mod tests { let proven = "aa11node"; // (1) Gateway-typed, hosted on the proven node → honored. - assert!(origin_user_backed(&[row(proven, Some(GATEWAY_TAG))], proven)); + assert!(origin_user_backed( + &[row(proven, Some(GATEWAY_TAG))], + proven + )); // (2) A non-Gateway (agent / other) type → re-stamped. - assert!(!origin_user_backed(&[row(proven, Some("live_agent"))], proven)); - assert!(!origin_user_backed(&[row(proven, Some("ready_agent"))], proven)); + assert!(!origin_user_backed( + &[row(proven, Some("live_agent"))], + proven + )); + assert!(!origin_user_backed( + &[row(proven, Some("ready_agent"))], + proven + )); // (3) No endpoint_type advertised (an N-1 node) → re-stamped (rollout grace). assert!(!origin_user_backed(&[row(proven, None)], proven)); // (4) A Gateway row exists, but on a DIFFERENT node than the proven // origin — keying is on the proven node, never the wire `from`. - assert!(!origin_user_backed(&[row("bb22other", Some(GATEWAY_TAG))], proven)); + assert!(!origin_user_backed( + &[row("bb22other", Some(GATEWAY_TAG))], + proven + )); // …and a mix where the proven node is agent-typed while another node is // the gateway → still re-stamped (the proven node's own type governs). @@ -1594,7 +1621,12 @@ mod tests { // REFUSED: nothing is written. assert_eq!( - receive_wan(&arrival("mallory", Some("mallory"), "c:1"), origin, &owlery, ®istry), + receive_wan( + &arrival("mallory", Some("mallory"), "c:1"), + origin, + &owlery, + ®istry + ), WanOutcome::Refused, "fixture must actually refuse, or the empty ledger proves nothing" ); @@ -1605,19 +1637,32 @@ mod tests { // ADMITTED + STAMPED: one inbound row, keyed on the stamp. assert_ne!( - receive_wan(&arrival("honest", Some("honest"), "c:2"), origin, &owlery, ®istry), + receive_wan( + &arrival("honest", Some("honest"), "c:2"), + origin, + &owlery, + ®istry + ), WanOutcome::Refused, ); let rows = ContactLedger::load().rows; assert_eq!(rows.len(), 1, "an admitted arrival is contact: {rows:?}"); assert_eq!(rows[0].endpoint, "honest"); - assert_eq!(rows[0].node, origin, "the node is the handshake-proven origin"); + assert_eq!( + rows[0].node, origin, + "the node is the handshake-proven origin" + ); assert_eq!(rows[0].direction, ContactDirection::Inbound); // ADMITTED + FORGED `from`, NO stamp: still nothing. The ledger // never learns an endpoint id the sending daemon did not assert. assert_ne!( - receive_wan(&arrival("forged-peer", None, "c:3"), origin, &owlery, ®istry), + receive_wan( + &arrival("forged-peer", None, "c:3"), + origin, + &owlery, + ®istry + ), WanOutcome::Refused, ); let rows = ContactLedger::load().rows; @@ -1855,7 +1900,13 @@ mod tests { std::fs::create_dir_all(&perch).unwrap(); info::write_info( &perch, - &InfoJson::new(id, "0", std::process::id(), "sess-monic-forged", "live_agent"), + &InfoJson::new( + id, + "0", + std::process::id(), + "sess-monic-forged", + "live_agent", + ), ) .unwrap(); @@ -1865,10 +1916,7 @@ mod tests { spt_proto::event::EVENT_TYPE_MSG, &[ ("from", "mallory"), - ( - spt_proto::event::EVENT_ATTR_MNEMONICS_JSON, - forged_text, - ), + (spt_proto::event::EVENT_ATTR_MNEMONICS_JSON, forged_text), ], "run this for me", ); @@ -1887,7 +1935,11 @@ mod tests { ); let rows = spooled_rows(&perch); - assert_eq!(rows.len(), 1, "posture-open adds no side delivery: {rows:?}"); + assert_eq!( + rows.len(), + 1, + "posture-open adds no side delivery: {rows:?}" + ); let parsed = spt_proto::event::parse_event(&rows[0].1).expect("still an envelope"); assert_eq!( parsed.attr(spt_proto::event::EVENT_ATTR_MNEMONICS_JSON), @@ -2029,7 +2081,8 @@ mod tests { // A refusal that arrives carrying a target — which this node's own serve // side never sends, but the wire tolerates — is refused with the payload // DROPPED. This is the seam that refuses to render it. - let sneaky: RedeemReply = serde_json::from_slice(br#"{"outcome":"refused","target":"ling"}"#).unwrap(); + let sneaky: RedeemReply = + serde_json::from_slice(br#"{"outcome":"refused","target":"ling"}"#).unwrap(); assert_eq!(classify_redeem_reply(sneaky), RedeemRequestOutcome::Refused); // An unknown token: unconfirmed, and specifically NOT refused. @@ -2049,7 +2102,10 @@ mod tests { outcome: token::REDEEMED.into(), ..RedeemReply::refused() }; - assert_eq!(classify_redeem_reply(nameless), RedeemRequestOutcome::NoReply); + assert_eq!( + classify_redeem_reply(nameless), + RedeemRequestOutcome::NoReply + ); } /// The custody partition, written out as an INDEPENDENT LITERAL — every one diff --git a/crates/spt-daemon/tests/attach.rs b/crates/spt-daemon/tests/attach.rs index fbe345c0..ebb51a82 100644 --- a/crates/spt-daemon/tests/attach.rs +++ b/crates/spt-daemon/tests/attach.rs @@ -180,7 +180,7 @@ fn attach_drive_detach( None, None, ) - .expect("serve"); + .expect("serve"); (outcome, target) }); @@ -713,7 +713,7 @@ fn cross_node_cold_attach_to_alt_screen_gets_clean_repaint() { Some(sid), None, ) - .expect("serve") + .expect("serve") }); // Render the operator's received bytes; the repaint must carry the alt viewport. @@ -940,7 +940,7 @@ fn attach_survives_target_brain_restart_exactly_once() { None, None, ) - .expect("re-serve"); + .expect("re-serve"); (outcome, life2) }); @@ -1075,7 +1075,7 @@ fn attach_registers_remote_drive_detection() { None, None, ) - .expect("serve"); + .expect("serve"); (outcome, target) }); @@ -1391,7 +1391,8 @@ fn wedged_viewer_does_not_stall_controller() { spt_daemon::brain::PumpTrace::Stderr, ) .expect("controller pump conn"); - ctrl.attach_as(sid, 0, AttachIntent::Control, 0, Some("node-A")).expect("control"); + ctrl.attach_as(sid, 0, AttachIntent::Control, 0, Some("node-A")) + .expect("control"); assert_eq!(read_outcome(&mut ctrl), SubscribeOutcome::Controller); // A viewer attaches but then NEVER reads — its writer thread blocks on the @@ -1509,8 +1510,8 @@ fn viewer_reads_marker_no_displace(brain: &mut Brain, needle: &[u8]) -> bool { } } Ok(BrokerEvent::Displaced { .. }) => panic!("a viewer must NEVER receive Displaced"), - Ok(_) => continue, // Size / other — keep reading - Err(_) => continue, // slice timeout — keep waiting until the deadline + Ok(_) => continue, // Size / other — keep reading + Err(_) => continue, // slice timeout — keep waiting until the deadline } } false diff --git a/crates/spt-daemon/tests/brain_decouple.rs b/crates/spt-daemon/tests/brain_decouple.rs index f4bc0354..e2c69978 100644 --- a/crates/spt-daemon/tests/brain_decouple.rs +++ b/crates/spt-daemon/tests/brain_decouple.rs @@ -165,7 +165,10 @@ fn subscribe( from_seq: 0, intent, by, - gen: 0, code: None, seal_ceremony: false, }) + gen: 0, + code: None, + seal_ceremony: false, + }) .unwrap(), ); loop { @@ -268,7 +271,10 @@ fn suspended_brain_controller_is_stall_evicted_take_completes_viewer_ticks() { from_seq: 0, intent: AttachIntent::Control, by: Some("operator-one".to_string()), - gen: 0, code: None, seal_ceremony: false, }) + gen: 0, + code: None, + seal_ceremony: false, + }) .unwrap(), ); // Read ONLY the subscribed reply, then go silent forever holding the conn. @@ -304,7 +310,10 @@ fn suspended_brain_controller_is_stall_evicted_take_completes_viewer_ticks() { from_seq: 0, intent: AttachIntent::Viewer, by: Some("viewer-node".to_string()), - gen: 0, code: None, seal_ceremony: false, }) + gen: 0, + code: None, + seal_ceremony: false, + }) .unwrap(), ); while let Ok(f) = read_frame(&mut v) { @@ -526,7 +535,10 @@ fn non_draining_controller_stall_evict_releases_writer_and_connection() { from_seq: 0, intent: AttachIntent::Control, by: Some("operator-one".to_string()), - gen: 0, code: None, seal_ceremony: false, }) + gen: 0, + code: None, + seal_ceremony: false, + }) .unwrap(), ); // Read until SUBSCRIBED. @@ -715,7 +727,10 @@ fn non_draining_controller_stall_evict_releases_writer_and_connection() { from_seq: resume_seq, intent: AttachIntent::Control, by: Some("operator-two".to_string()), - gen: 0, code: None, seal_ceremony: false, }) + gen: 0, + code: None, + seal_ceremony: false, + }) .unwrap(), ); // Single loop: capture the outcome (on SUBSCRIBED) AND the first replayed diff --git a/crates/spt-daemon/tests/broker.rs b/crates/spt-daemon/tests/broker.rs index 4e9b9f2e..248b3ba8 100644 --- a/crates/spt-daemon/tests/broker.rs +++ b/crates/spt-daemon/tests/broker.rs @@ -345,12 +345,18 @@ fn env_inject_test() { #[cfg(unix)] let (program, args) = ( "sh".to_string(), - vec!["-c".to_string(), "echo ENVCHECK=$SPT_ENDPOINT_ID".to_string()], + vec![ + "-c".to_string(), + "echo ENVCHECK=$SPT_ENDPOINT_ID".to_string(), + ], ); #[cfg(windows)] let (program, args) = ( "cmd".to_string(), - vec!["/c".to_string(), "echo ENVCHECK=%SPT_ENDPOINT_ID%".to_string()], + vec![ + "/c".to_string(), + "echo ENVCHECK=%SPT_ENDPOINT_ID%".to_string(), + ], ); let mut env = std::collections::BTreeMap::new(); env.insert("SPT_ENDPOINT_ID".to_string(), "wall-b".to_string()); @@ -452,9 +458,15 @@ fn dead_session_subscribe_test() { // A child that exits immediately. #[cfg(unix)] - let (program, args) = ("sh".to_string(), vec!["-c".to_string(), "exit 0".to_string()]); + let (program, args) = ( + "sh".to_string(), + vec!["-c".to_string(), "exit 0".to_string()], + ); #[cfg(windows)] - let (program, args) = ("cmd".to_string(), vec!["/c".to_string(), "exit".to_string()]); + let (program, args) = ( + "cmd".to_string(), + vec!["/c".to_string(), "exit".to_string()], + ); send( &mut conn, KIND_SPAWN, @@ -476,7 +488,11 @@ fn dead_session_subscribe_test() { for _ in 0..200 { match read_frame(&mut conn) { Ok(f) if f.kind == KIND_SPAWNED => { - sid = Some(serde_json::from_value::(f.payload).unwrap().session_id); + sid = Some( + serde_json::from_value::(f.payload) + .unwrap() + .session_id, + ); break; } Ok(_) => {} @@ -497,7 +513,10 @@ fn dead_session_subscribe_test() { from_seq: 0, intent: Default::default(), by: None, - gen: 0, code: None, seal_ceremony: false, }) + gen: 0, + code: None, + seal_ceremony: false, + }) .unwrap(), ); for _ in 0..30 { @@ -580,11 +599,10 @@ fn wall_b_composition_test() { [env.SPT_ENDPOINT_ID]\ndirection = \"inject\"\nvalue = \"{{id}}\"\n" ); let manifest = spt_runtime::Manifest::from_toml_str(&manifest_toml).unwrap(); - let prepared = - spt_daemon::harnesshost::prepare_harness_spawn( - "wall-b", "mock", "sid-1", &manifest, false, None, None, - ) - .expect("prepare"); + let prepared = spt_daemon::harnesshost::prepare_harness_spawn( + "wall-b", "mock", "sid-1", &manifest, false, None, None, + ) + .expect("prepare"); // F-013: the id is filled into the env value (not empty). assert_eq!( prepared.env.get("SPT_ENDPOINT_ID").map(String::as_str), @@ -708,7 +726,11 @@ fn connect_brain(name: &str) -> Stream { /// Spawn the long-lived echo child and return its session id (draining any /// interleaved early output into `out`). fn spawn_echo(conn: &mut Stream, out: &mut Vec) -> u64 { - send(conn, KIND_SPAWN, serde_json::to_value(echo_spawn_req()).unwrap()); + send( + conn, + KIND_SPAWN, + serde_json::to_value(echo_spawn_req()).unwrap(), + ); loop { let f = read_frame(conn).expect("frame before spawned"); match f.kind.as_str() { @@ -1030,7 +1052,9 @@ fn controller_writer_reorder_test() { let sid = loop { let f = read_frame(&mut conn).expect("frame before spawned"); if f.kind == KIND_SPAWNED { - break serde_json::from_value::(f.payload).unwrap().session_id; + break serde_json::from_value::(f.payload) + .unwrap() + .session_id; } }; @@ -1100,7 +1124,10 @@ fn controller_writer_reorder_test() { } } } - let last_live_seq = *dedup.accepted_seqs.last().expect("at least one chunk accepted"); + let last_live_seq = *dedup + .accepted_seqs + .last() + .expect("at least one chunk accepted"); assert!( last_live_seq >= 1, "the ring must hold at least seqs 0 and 1 before the double-subscribe \ @@ -1124,7 +1151,10 @@ fn controller_writer_reorder_test() { from_seq: floor, intent: Default::default(), // Control by: None, - gen: 0, code: None, seal_ceremony: false, }) + gen: 0, + code: None, + seal_ceremony: false, + }) .unwrap(), ); } @@ -1206,9 +1236,7 @@ fn controller_writer_reorder_test() { } fn contains(haystack: &[u8], needle: &[u8]) -> bool { - haystack - .windows(needle.len()) - .any(|w| w == needle) + haystack.windows(needle.len()).any(|w| w == needle) } // [int->REQ-HAZARD-CONTROLLER-WRITER-REORDER] diff --git a/crates/spt-daemon/tests/commune_io_events_int.rs b/crates/spt-daemon/tests/commune_io_events_int.rs index 9f3faac1..cafbc3e2 100644 --- a/crates/spt-daemon/tests/commune_io_events_int.rs +++ b/crates/spt-daemon/tests/commune_io_events_int.rs @@ -58,11 +58,7 @@ fn linked_shell(owner: &str) -> (std::path::PathBuf, String, [u8; 32]) { let sp = perch::resolve_shell_perch_path_in(&owlery, owner, &shell_id); std::fs::create_dir_all(&sp).unwrap(); let token = "commune-io-int-token"; - std::fs::write( - sp.join(spt_daemon::shellhost::LINK_TOKEN_FILE), - token, - ) - .unwrap(); + std::fs::write(sp.join(spt_daemon::shellhost::LINK_TOKEN_FILE), token).unwrap(); (owlery, shell_id, spt_daemon::shellhost::link_key(token)) } @@ -129,15 +125,16 @@ fn a_consumed_commune_and_a_failed_ingest_reach_a_shell_as_distinct_events() { let project_dir = tempfile::tempdir().unwrap(); let owner_perch = perch::resolve_perch_path(owner, ParentHint::Infer); std::fs::create_dir_all(&owner_perch).unwrap(); - let mut rec = spt_store::info::InfoJson::new(owner, "0", std::process::id(), "sid-1", "live_agent"); + let mut rec = + spt_store::info::InfoJson::new(owner, "0", std::process::id(), "sid-1", "live_agent"); rec.cwd = Some(project_dir.path().to_string_lossy().to_string()); spt_store::info::write_info(&owner_perch, &rec).unwrap(); let drops = tempfile::tempdir().unwrap(); let drop_path = drops.path().join(format!("{owner}-commune.md")); let manifest = live_manifest(drops.path()); - let host = BrainLifecycle::with_config(&manifest, owner, DaemonConfig::default()) - .expect("live host"); + let host = + BrainLifecycle::with_config(&manifest, owner, DaemonConfig::default()).expect("live host"); let (owlery, shell_id, key) = linked_shell(owner); // ── (1) A REAL CONSUMPTION. The body is deliberately awkward: a `!!wake!!` @@ -149,7 +146,11 @@ fn a_consumed_commune_and_a_failed_ingest_reach_a_shell_as_distinct_events() { std::fs::write(&drop_path, body).unwrap(); let report = host.pulse_tick(Some("sid-1")).expect("tick"); - assert_eq!(report.ingested.len(), 1, "PRECONDITION: the drop was ingested"); + assert_eq!( + report.ingested.len(), + 1, + "PRECONDITION: the drop was ingested" + ); assert!( !drop_path.exists(), "PRECONDITION: a consumed drop is unlinked — which is why the event must carry its bytes" @@ -191,7 +192,9 @@ fn a_consumed_commune_and_a_failed_ingest_reach_a_shell_as_distinct_events() { blocked.display() ); - let report = host.pulse_tick(Some("sid-1")).expect("tick survives a failed ingest"); + let report = host + .pulse_tick(Some("sid-1")) + .expect("tick survives a failed ingest"); assert!( report.ingested.is_empty(), "PRECONDITION: the ingest FAILED — nothing was folded in: {:?}", diff --git a/crates/spt-daemon/tests/conn_blackhole_lifecycle.rs b/crates/spt-daemon/tests/conn_blackhole_lifecycle.rs index dc2b067d..f681c15f 100644 --- a/crates/spt-daemon/tests/conn_blackhole_lifecycle.rs +++ b/crates/spt-daemon/tests/conn_blackhole_lifecycle.rs @@ -277,7 +277,10 @@ fn blackholed_controller_lifecycle_five_invariants() { from_seq: 0, intent: AttachIntent::Viewer, by: Some("unrelated-viewer".to_string()), - gen: 0, code: None, seal_ceremony: false, }) + gen: 0, + code: None, + seal_ceremony: false, + }) .unwrap(), ); while let Ok(f) = read_frame(&mut v) { @@ -313,7 +316,10 @@ fn blackholed_controller_lifecycle_five_invariants() { from_seq: 0, intent: AttachIntent::Control, by: Some("operator-one".to_string()), - gen: 0, code: None, seal_ceremony: false, }) + gen: 0, + code: None, + seal_ceremony: false, + }) .unwrap(), ); loop { @@ -536,7 +542,10 @@ fn blackholed_controller_lifecycle_five_invariants() { from_seq: resume_seq, intent: AttachIntent::Viewer, by: Some("fresh-viewer".to_string()), - gen: 0, code: None, seal_ceremony: false, }) + gen: 0, + code: None, + seal_ceremony: false, + }) .unwrap(), ); // The writer thread resolve_subscribe spawns races the inline SUBSCRIBED diff --git a/crates/spt-daemon/tests/controller_lease.rs b/crates/spt-daemon/tests/controller_lease.rs index 0ab4b7bf..e0d11ce7 100644 --- a/crates/spt-daemon/tests/controller_lease.rs +++ b/crates/spt-daemon/tests/controller_lease.rs @@ -148,7 +148,10 @@ fn request_attach_with_gen( from_seq: 0, intent, endpoint_id: None, - gen, code: None, seal_ceremony: false, }); + gen, + code: None, + seal_ceremony: false, + }); brain .net_stream_send(opened.stream_id, &line, None, false) .expect("send Request"); diff --git a/crates/spt-daemon/tests/daemon_lifecycle_real_brain.rs b/crates/spt-daemon/tests/daemon_lifecycle_real_brain.rs index 19f9fe89..548c3b37 100644 --- a/crates/spt-daemon/tests/daemon_lifecycle_real_brain.rs +++ b/crates/spt-daemon/tests/daemon_lifecycle_real_brain.rs @@ -66,7 +66,8 @@ fn real_brain_process_hosts_the_psyche_for_an_online_live_endpoint() { let id = "agent9"; let perch_path = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&perch_path).unwrap(); - let mut rec = spt_store::info::InfoJson::new(id, "t", std::process::id(), "sid-9", "live_agent"); + let mut rec = + spt_store::info::InfoJson::new(id, "t", std::process::id(), "sid-9", "live_agent"); rec.adapter = Some("mock".to_string()); spt_store::info::write_info(&perch_path, &rec).unwrap(); spt_store::info::set_status(&perch_path, STATUS_ONLINE).unwrap(); diff --git a/crates/spt-daemon/tests/digest.rs b/crates/spt-daemon/tests/digest.rs index 3b43faee..3fca55cb 100644 --- a/crates/spt-daemon/tests/digest.rs +++ b/crates/spt-daemon/tests/digest.rs @@ -31,7 +31,11 @@ use spt_store::perch::{self, resolve_perch_path, ParentHint}; static SEQ: AtomicU32 = AtomicU32::new(0); fn unique(prefix: &str) -> String { let n = SEQ.fetch_add(1, Ordering::Relaxed); - format!("spt-daemon-digest-{prefix}-{}-{}.sock", std::process::id(), n) + format!( + "spt-daemon-digest-{prefix}-{}-{}.sock", + std::process::id(), + n + ) } /// A stdin pass-through "extractor": the source bytes (piped in) round-trip to @@ -57,7 +61,9 @@ fn establish_cc_endpoint(id: &str, fixture: &std::path::Path) { PASSTHROUGH, fixture.display(), ); - let src = perch::spt_home().join("srcs").join(format!("{adapter}-src")); + let src = perch::spt_home() + .join("srcs") + .join(format!("{adapter}-src")); std::fs::create_dir_all(&src).unwrap(); std::fs::write(src.join("manifest.toml"), manifest).unwrap(); spt_runtime::registry::register(&perch::adapters_dir(), &src, 1000).unwrap(); @@ -118,7 +124,7 @@ fn harness_hosted_digest_projects_and_pushes_deltas() { pull_snapshot(&digest_name, "cc", DigestOverride::default()) }) .expect("pull ok") - .expect("a digest projects for the harness-hosted endpoint"); + .expect("a digest projects for the harness-hosted endpoint"); assert!(version >= 1, "the projection has a version"); assert_eq!(digest.turns.len(), 1, "one user turn: {digest:?}"); assert_eq!(digest.turns[0].input.as_deref(), Some("add a file")); @@ -174,7 +180,10 @@ fn harness_hosted_digest_projects_and_pushes_deltas() { reproject(&digest_name, "cc2").expect("nudge a re-projection"); let got = wait_recv(&rx, Duration::from_secs(5)); - assert!(got.is_some(), "the subscriber received the push-driven delta"); + assert!( + got.is_some(), + "the subscriber received the push-driven delta" + ); } /// Block up to `dur` for one value on `rx`. diff --git a/crates/spt-daemon/tests/digest_cross_node.rs b/crates/spt-daemon/tests/digest_cross_node.rs index 3a39baa8..39bd701d 100644 --- a/crates/spt-daemon/tests/digest_cross_node.rs +++ b/crates/spt-daemon/tests/digest_cross_node.rs @@ -140,26 +140,26 @@ fn spawn_dispatcher_for(broker_name: &str, scratch: &std::path::Path) -> Arc Arcthe book index").unwrap(); std::fs::write(root.join("llms-full.txt"), b"# full docs export bytes").unwrap(); - std::fs::write(root.join("cli").join("reference.md"), b"# CLI reference raw md").unwrap(); + std::fs::write( + root.join("cli").join("reference.md"), + b"# CLI reference raw md", + ) + .unwrap(); std::fs::write(root.join("manifest.schema.json"), b"{\"$id\":\"schema\"}").unwrap(); // A file OUTSIDE the docs root — the traversal target that must stay // unreachable. @@ -62,7 +66,10 @@ fn serves_published_surface_and_refuses_escapes_and_writes() { // The published URL surface, byte-true (llms contract verbatim). let (status, head, body) = get(port, "/"); assert!(status.contains("200"), "{status}"); - assert!(head.to_lowercase().contains("content-type: text/html"), "{head}"); + assert!( + head.to_lowercase().contains("content-type: text/html"), + "{head}" + ); assert_eq!(body, b"the book index", "index byte-true"); let (status, _, body) = get(port, "/llms-full.txt"); @@ -71,7 +78,10 @@ fn serves_published_surface_and_refuses_escapes_and_writes() { let (status, head, body) = get(port, "/cli/reference.md"); assert!(status.contains("200"), "{status}"); - assert!(head.to_lowercase().contains("text/plain"), "raw md is plain: {head}"); + assert!( + head.to_lowercase().contains("text/plain"), + "raw md is plain: {head}" + ); assert_eq!(body, b"# CLI reference raw md", "append-.md twin byte-true"); let (status, head, _) = get(port, "/manifest.schema.json"); @@ -79,7 +89,11 @@ fn serves_published_surface_and_refuses_escapes_and_writes() { assert!(head.to_lowercase().contains("application/json"), "{head}"); // Traversal shapes: rejected, and the outside file never leaks. - for bad in ["/../secret.txt", "/%2e%2e/secret.txt", "/cli/../../secret.txt"] { + for bad in [ + "/../secret.txt", + "/%2e%2e/secret.txt", + "/cli/../../secret.txt", + ] { let (status, _, body) = get(port, bad); assert!( status.contains("400") || status.contains("404"), diff --git a/crates/spt-daemon/tests/endpoint_lifecycle.rs b/crates/spt-daemon/tests/endpoint_lifecycle.rs index 2b91ad73..aed4adc1 100644 --- a/crates/spt-daemon/tests/endpoint_lifecycle.rs +++ b/crates/spt-daemon/tests/endpoint_lifecycle.rs @@ -291,9 +291,9 @@ fn dead_relay_converges_while_its_live_sibling_still_delivers() { let mut rec = spt_store::info::InfoJson::new(&dead, "t", relay_pid, "sid-relay", "live_agent"); rec.pid_started_at = relay_birth; rec.parent_pid = Some(std::process::id()); // the OWNER outlives the relay - // The recorded pid HOLDS this endpoint — an `api listen` relay. Convergence is - // role-gated (REQ-PID-ROLE-EVIDENCE), so without this the row would be spared as - // "no knowledge" and this test would pass for the WRONG REASON. + // The recorded pid HOLDS this endpoint — an `api listen` relay. Convergence is + // role-gated (REQ-PID-ROLE-EVIDENCE), so without this the row would be spared as + // "no knowledge" and this test would pass for the WRONG REASON. rec.pid_role = Some(spt_store::info::PidRole::Relay); // controllable stays None: harness-hosted, no broker PTY — the exempt row. spt_store::info::write_info(&dead_perch, &rec).unwrap(); @@ -321,13 +321,8 @@ fn dead_relay_converges_while_its_live_sibling_still_delivers() { let live = format!("relaylive-{}", std::process::id()); let live_perch = perch::resolve_perch_path(&live, ParentHint::Infer); std::fs::create_dir_all(&live_perch).unwrap(); - let mut rec = spt_store::info::InfoJson::new( - &live, - "t", - std::process::id(), - "sid-sibling", - "live_agent", - ); + let mut rec = + spt_store::info::InfoJson::new(&live, "t", std::process::id(), "sid-sibling", "live_agent"); rec.pid_started_at = spt_store::proc::process_started_at(std::process::id()); spt_store::info::write_info(&live_perch, &rec).unwrap(); spt_store::info::set_status(&live_perch, spt_store::liveness::STATUS_ONLINE).unwrap(); @@ -384,7 +379,11 @@ fn dead_relay_converges_while_its_live_sibling_still_delivers() { ); // ── Sibling probe: delivery to the LIVE relay still works, after all that. ── - assert_eq!(read_info(&live).status.as_deref(), Some("online"), "sibling untouched"); + assert_eq!( + read_info(&live).status.as_deref(), + Some("online"), + "sibling untouched" + ); let outcome = spt_msg::deliver::send(&live, "prober", "still-here", &owlery); assert_eq!( outcome, @@ -515,7 +514,11 @@ fn an_inherited_stamp_from_a_dead_relay_converges_while_a_dead_binder_row_stays_ converges — got {offlined:?}" ); let after = read_info(&ghost); - assert_eq!(after.status.as_deref(), Some("offline"), "ghost status converged"); + assert_eq!( + after.status.as_deref(), + Some("offline"), + "ghost status converged" + ); assert!( !perch::resolve_ready_file(&ghost, ParentHint::Infer).exists(), "ready marker cleared — the projection agrees with itself again" diff --git a/crates/spt-daemon/tests/er_inbound_local_notify.rs b/crates/spt-daemon/tests/er_inbound_local_notify.rs index 1f5ff70b..0bed3995 100644 --- a/crates/spt-daemon/tests/er_inbound_local_notify.rs +++ b/crates/spt-daemon/tests/er_inbound_local_notify.rs @@ -40,7 +40,13 @@ fn seed_online_perch(owlery: &std::path::Path, id: &str, last_active: u64) -> st std::fs::create_dir_all(&p).expect("perch dir"); info::write_info( &p, - &InfoJson::new(id, "t", std::process::id(), &format!("sid-{id}"), "live_agent"), + &InfoJson::new( + id, + "t", + std::process::id(), + &format!("sid-{id}"), + "live_agent", + ), ) .expect("write info"); set_status(&p, STATUS_ONLINE).expect("status"); @@ -56,7 +62,9 @@ fn home_policy() -> NotifSurfacePolicy { } fn spooled(perch: &std::path::Path) -> usize { - spt_store::spool::peek_all_at(perch).map(|r| r.len()).unwrap_or(0) + spt_store::spool::peek_all_at(perch) + .map(|r| r.len()) + .unwrap_or(0) } // [int->REQ-ER-INBOUND-LOCK-ALL-PATHS] diff --git a/crates/spt-daemon/tests/false_promote.rs b/crates/spt-daemon/tests/false_promote.rs index d9f7d164..22182765 100644 --- a/crates/spt-daemon/tests/false_promote.rs +++ b/crates/spt-daemon/tests/false_promote.rs @@ -164,7 +164,10 @@ fn remote_take(name: &str, sid: u64) { from_seq: 0, intent: AttachIntent::Control, by: Some("operator-two".to_string()), - gen: 0, code: None, seal_ceremony: false, }) + gen: 0, + code: None, + seal_ceremony: false, + }) .unwrap(), ); loop { diff --git a/crates/spt-daemon/tests/fixtures/dispatch_fixture.rs b/crates/spt-daemon/tests/fixtures/dispatch_fixture.rs index 2940bf6d..98f491a3 100644 --- a/crates/spt-daemon/tests/fixtures/dispatch_fixture.rs +++ b/crates/spt-daemon/tests/fixtures/dispatch_fixture.rs @@ -12,7 +12,9 @@ use std::sync::Arc; use std::time::Duration; fn main() { - let broker = std::env::args().nth(1).expect("usage: dispatch_fixture "); + let broker = std::env::args() + .nth(1) + .expect("usage: dispatch_fixture "); let registry = Arc::new(spt_daemon::registryhost::RegistryHost::new_at( "fixturenode", spt_store::epoch::EpochSource::load_from(&spt_store::perch::epoch_file()), diff --git a/crates/spt-daemon/tests/fixtures/service_fixture.rs b/crates/spt-daemon/tests/fixtures/service_fixture.rs index fc3e9906..98794a95 100644 --- a/crates/spt-daemon/tests/fixtures/service_fixture.rs +++ b/crates/spt-daemon/tests/fixtures/service_fixture.rs @@ -161,7 +161,8 @@ fn try_spt_send(dir: &Path) { return; }; let mut cmd = std::process::Command::new(&bin); - cmd.args(["send", &target]).stdin(std::process::Stdio::piped()); + cmd.args(["send", &target]) + .stdin(std::process::Stdio::piped()); let Ok(mut child) = cmd .stdout(std::process::Stdio::piped()) .stderr(std::process::Stdio::piped()) @@ -222,7 +223,11 @@ fn main() { write(&dir, BEACON, &std::process::id().to_string()); dump_env(&dir); - write(&dir, STATUS_ADVISORY, "mock advisory: serving\nsecond line must never be read\n"); + write( + &dir, + STATUS_ADVISORY, + "mock advisory: serving\nsecond line must never be read\n", + ); match mode.as_str() { // Ignores the stop marker entirely — the wedged service the grace @@ -251,4 +256,3 @@ fn main() { _ => serve(&dir, true, Duration::ZERO), } } - diff --git a/crates/spt-daemon/tests/idempotent.rs b/crates/spt-daemon/tests/idempotent.rs index 9417e12d..0f4c3c93 100644 --- a/crates/spt-daemon/tests/idempotent.rs +++ b/crates/spt-daemon/tests/idempotent.rs @@ -32,7 +32,7 @@ use std::thread; use std::time::Duration; use spt_daemon::brain::{Brain, BrainState, BrokerEvent}; -use spt_daemon::effect::{EffectKey, Minter, MintedOp}; +use spt_daemon::effect::{EffectKey, MintedOp, Minter}; use spt_daemon::msg::SpawnReq; use spt_daemon::Broker; diff --git a/crates/spt-daemon/tests/inject_control_wedge.rs b/crates/spt-daemon/tests/inject_control_wedge.rs index f907c1c4..528a2742 100644 --- a/crates/spt-daemon/tests/inject_control_wedge.rs +++ b/crates/spt-daemon/tests/inject_control_wedge.rs @@ -534,26 +534,26 @@ fn large_endpoint_inject_to_a_no_binary_session_spools_promptly_without_wedging( /// touch a real home). fn init_wedge_home() -> TestHome { let home = TestHome::new(); - // F-036 env-inheritance scrub (doyle RCA, REDISPATCH-STALL gate round - // 1): a live-agent dev shell exports SPT_INJECT_VERIFY_ECHO, the - // in-process test broker inherits it, Layer-2 echo-verify force- - // enables host-wide, and the mock PTY children here never re-render - // typed input → echo-verify miss → respool-once = a spurious - // delivered-plus-spool-row red on exactly the boxes developers run - // gates on. The runtime spawns already scrub these - // (spt_runtime::INJECT_ECHO_ENV_VARS); the test rigs must too. The - // opt-in echo-miss test sets them itself AFTER this init → its set - // wins (the SPT_INJECT_SETTLE_MS precedent above). - for var in spt_runtime::INJECT_ECHO_ENV_VARS { - std::env::remove_var(var); - } + // F-036 env-inheritance scrub (doyle RCA, REDISPATCH-STALL gate round + // 1): a live-agent dev shell exports SPT_INJECT_VERIFY_ECHO, the + // in-process test broker inherits it, Layer-2 echo-verify force- + // enables host-wide, and the mock PTY children here never re-render + // typed input → echo-verify miss → respool-once = a spurious + // delivered-plus-spool-row red on exactly the boxes developers run + // gates on. The runtime spawns already scrub these + // (spt_runtime::INJECT_ECHO_ENV_VARS); the test rigs must too. The + // opt-in echo-miss test sets them itself AFTER this init → its set + // wins (the SPT_INJECT_SETTLE_MS precedent above). + for var in spt_runtime::INJECT_ECHO_ENV_VARS { + std::env::remove_var(var); + } // W5-A: shrink the settle-gate timeout for each test. The mock PTY children here - // (findstr/cat) never answer the DSR readiness probe, so the settle-gate always - // elapses its bounded wait once per worker — its PRESENCE is the invariant, not - // the length, so 80ms keeps the suite fast and removes the fixed-sleep timing - // perturbation the default 400ms introduced (a test that needs a specific value - // sets `SPT_INJECT_SETTLE_MS` itself, AFTER this init → its set wins). - std::env::set_var("SPT_INJECT_SETTLE_MS", "80"); + // (findstr/cat) never answer the DSR readiness probe, so the settle-gate always + // elapses its bounded wait once per worker — its PRESENCE is the invariant, not + // the length, so 80ms keeps the suite fast and removes the fixed-sleep timing + // perturbation the default 400ms introduced (a test that needs a specific value + // sets `SPT_INJECT_SETTLE_MS` itself, AFTER this init → its set wins). + std::env::set_var("SPT_INJECT_SETTLE_MS", "80"); home } diff --git a/crates/spt-daemon/tests/input_ack_deadlock.rs b/crates/spt-daemon/tests/input_ack_deadlock.rs index 278580b0..2b6659c9 100644 --- a/crates/spt-daemon/tests/input_ack_deadlock.rs +++ b/crates/spt-daemon/tests/input_ack_deadlock.rs @@ -416,9 +416,7 @@ fn input_flood_through_serve_attach_does_not_deadlock_broker() { // return direction and wedge the broker's per-conn handler. for op in 1..=FLOOD_N { let line = format!("FLOODINPUT-{op}\r"); - if let Err(error) = - send_attach_input(&mut operator, stream, line.as_bytes(), op) - { + if let Err(error) = send_attach_input(&mut operator, stream, line.as_bytes(), op) { let _ = flood_tx.send(FloodVerdict::SendFailed { op, error: format!("{error:#}"), @@ -446,9 +444,7 @@ fn input_flood_through_serve_attach_does_not_deadlock_broker() { let flood_verdict = match flood_rx.recv_timeout(Duration::from_secs(20)) { Ok(verdict) => verdict, Err(std::sync::mpsc::RecvTimeoutError::Timeout) => FloodVerdict::WatchdogTimeout, - Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => { - FloodVerdict::HelperDisconnected - } + Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => FloodVerdict::HelperDisconnected, }; let (flood_sent, flood_detail) = match &flood_verdict { FloodVerdict::Sent => (true, "Sent".to_string()), diff --git a/crates/spt-daemon/tests/legacy_resident_sweep_e2e.rs b/crates/spt-daemon/tests/legacy_resident_sweep_e2e.rs index df37a862..12572167 100644 --- a/crates/spt-daemon/tests/legacy_resident_sweep_e2e.rs +++ b/crates/spt-daemon/tests/legacy_resident_sweep_e2e.rs @@ -157,7 +157,9 @@ fn legacy_resident_sweep_reaps_match_and_declines_control() { // SWEPT: the positive-match legacy wrapper is reaped ... assert!( - wait_until(Duration::from_secs(5), || !spt_store::proc::is_process_alive(mock_pid)), + wait_until(Duration::from_secs(5), || { + !spt_store::proc::is_process_alive(mock_pid) + }), "the matching legacy wrapper must be SWEPT (RED if the kill is bypassed)" ); // ... and its residue (the stale `-psyche` ready registration) is CLEARED. @@ -166,7 +168,8 @@ fn legacy_resident_sweep_reaps_match_and_declines_control() { "the stale `legacyhost-psyche` ready registration (info.json) must be cleared (pin 3)" ); assert!( - !perch::resolve_ready_file("legacyhost-psyche", ParentHint::Explicit("legacyhost")).exists(), + !perch::resolve_ready_file("legacyhost-psyche", ParentHint::Explicit("legacyhost")) + .exists(), "the stale `legacyhost-psyche` `ready` marker must be cleared (pin 3)" ); diff --git a/crates/spt-daemon/tests/mesh.rs b/crates/spt-daemon/tests/mesh.rs index f205ee19..e7c1f2e4 100644 --- a/crates/spt-daemon/tests/mesh.rs +++ b/crates/spt-daemon/tests/mesh.rs @@ -59,7 +59,7 @@ const SUBNET: &str = "mesh0"; static LOCK: Mutex<()> = Mutex::new(()); fn init_home() -> TestHome { let home = TestHome::new(); - std::env::set_var("SPT_NTP_SERVER", "off"); + std::env::set_var("SPT_NTP_SERVER", "off"); home } @@ -187,7 +187,9 @@ impl MeshNode { std::fs::create_dir_all(root).unwrap(); std::fs::write(root.join("noseed"), b"").unwrap(); // the seed blocker (a file) let mut subnets = SubnetStore::default(); - subnets.create_subnet(SUBNET, spt_store::access::Mode::Open).expect("node subnet"); + subnets + .create_subnet(SUBNET, spt_store::access::Mode::Open) + .expect("node subnet"); subnets.save_to(&paths.subnets).expect("save node subnet"); // The push target = the roster (Mesh-D6). Sibling of subnet.json so the // pump derives it (subnet.json → roster.json). Seeded empty here; the diff --git a/crates/spt-daemon/tests/mesh_recovery.rs b/crates/spt-daemon/tests/mesh_recovery.rs index d561b040..9e56897d 100644 --- a/crates/spt-daemon/tests/mesh_recovery.rs +++ b/crates/spt-daemon/tests/mesh_recovery.rs @@ -147,7 +147,9 @@ fn pump_node( }; std::fs::create_dir_all(root).unwrap(); let mut subnets = SubnetStore::default(); - subnets.create_subnet(subnet, spt_store::access::Mode::Open).expect("subnet"); + subnets + .create_subnet(subnet, spt_store::access::Mode::Open) + .expect("subnet"); subnets.save_to(&paths.subnets).expect("save subnets"); let mut roster = spt_store::roster::RosterStore::default(); roster.merge_entry(spt_store::roster::RosterEntry { @@ -174,7 +176,14 @@ fn spawn_pump( paths: PumpPaths, resolver: PeerResolver, ) -> Arc { - spawn_pump_with_hooks(broker, self_hex, root, paths, resolver, PumpHooks::default()) + spawn_pump_with_hooks( + broker, + self_hex, + root, + paths, + resolver, + PumpHooks::default(), + ) } /// As [`spawn_pump`], with the pump's observation hooks supplied — the seam @@ -210,15 +219,7 @@ fn spawn_pump_with_hooks( }, full_auto_update: false, }; - let out = run_peer_pump( - &name, - registry, - &paths, - resolver, - config, - hooks, - &flag, - ); + let out = run_peer_pump(&name, registry, &paths, resolver, config, hooks, &flag); eprintln!("TEST_PUMP_EXIT: {out:?}"); }); stop @@ -511,7 +512,10 @@ fn a_dead_roster_address_does_not_strand_the_peer_from_discovery() { { let self_status = a_probe.net_status().expect("status"); let self_addr = self_status.addr.clone(); - assert!(!self_addr.is_null(), "a bound endpoint reports its own address"); + assert!( + !self_addr.is_null(), + "a bound endpoint reports its own address" + ); assert_eq!( spt_store::peeraddrs::addr_peer_id(&self_addr), Some(a_hex.as_str()), diff --git a/crates/spt-daemon/tests/net_worker_starve.rs b/crates/spt-daemon/tests/net_worker_starve.rs index a8a4f4f1..9981dd30 100644 --- a/crates/spt-daemon/tests/net_worker_starve.rs +++ b/crates/spt-daemon/tests/net_worker_starve.rs @@ -80,8 +80,8 @@ fn proving(identity: Identity) -> NetConfig { /// via `broker.net()`. fn served_broker(name: &str, cfg: NetConfig, dir: &std::path::Path) -> Arc { let host = NetHost::start(cfg).expect("net host start"); - let broker = Broker::bind_in_with_net(name, dir.join("effects.log"), Some(host)) - .expect("bind broker"); + let broker = + Broker::bind_in_with_net(name, dir.join("effects.log"), Some(host)).expect("bind broker"); let serve = Arc::clone(&broker); thread::spawn(move || { let _ = serve.serve(); @@ -121,7 +121,11 @@ fn dead_peer_dial_burst_vs_net_runtime_canary() { host_a.set_quic_op_timeout(Duration::from_millis(3000)); // B: the black hole — accepts the handshake, never runs the proof responder. - let broker_b = served_broker(&name_b, hermetic(Identity::generate()), &dir.path().join("b")); + let broker_b = served_broker( + &name_b, + hermetic(Identity::generate()), + &dir.path().join("b"), + ); let host_b = broker_b.net().expect("host b"); let b_addr = host_b.addr(); let b_hex = host_b.node_id_hex(); @@ -133,7 +137,10 @@ fn dead_peer_dial_burst_vs_net_runtime_canary() { base_canary < 250, "baseline canary should be fresh (<250ms), got {base_canary}ms — probe broken?" ); - eprintln!("UW3 baseline: canary_age={base_canary}ms tasks={}", host_a.active_dial_tasks()); + eprintln!( + "UW3 baseline: canary_age={base_canary}ms tasks={}", + host_a.active_dial_tasks() + ); // Fire the burst: K concurrent dead-peer dials straight onto A's NetHost (the // exact pump path). K far exceeds the 2 workers so IF connects hold workers, @@ -198,7 +205,10 @@ fn unreachable_peer_dial_burst_vs_net_runtime_canary() { thread::sleep(Duration::from_millis(80)); let base_canary = host_a.net_canary_age_ms(); - assert!(base_canary < 250, "baseline canary fresh, got {base_canary}ms"); + assert!( + base_canary < 250, + "baseline canary fresh, got {base_canary}ms" + ); eprintln!("UW3-unreach baseline: canary_age={base_canary}ms"); const K: usize = 12; diff --git a/crates/spt-daemon/tests/netbroker.rs b/crates/spt-daemon/tests/netbroker.rs index b2beda39..c9af1f8d 100644 --- a/crates/spt-daemon/tests/netbroker.rs +++ b/crates/spt-daemon/tests/netbroker.rs @@ -22,7 +22,7 @@ use std::thread; use std::time::Duration; use spt_daemon::brain::Brain; -use spt_daemon::effect::{EffectKey, Minter, MintedOp}; +use spt_daemon::effect::{EffectKey, MintedOp, Minter}; use spt_daemon::nethost::{NetConfig, NetHost, NET_EFFECT_SESSION}; use spt_daemon::Broker; use spt_net::net::endpoint::{BindScope, LocalDiscovery, RelayPolicy}; @@ -165,13 +165,17 @@ fn replayed_dial_op_is_deduped_across_brain_restart() { const OP: u64 = 42; // Life 1: journaled dial, then "crash" (connection drop). let mut life1 = connect_retry(&name_a); - let first = life1.net_dial(addr.clone(), Some(MintedOp::new(Minter::Cli, OP))).expect("dial"); + let first = life1 + .net_dial(addr.clone(), Some(MintedOp::new(Minter::Cli, OP))) + .expect("dial"); assert!(first.applied_now, "first delivery runs the dial"); drop(life1); // Life 2: re-drives the same durable op (the brain never learned it landed). let mut life2 = connect_retry(&name_a); - let replay = life2.net_dial(addr, Some(MintedOp::new(Minter::Cli, OP))).expect("replayed dial"); + let replay = life2 + .net_dial(addr, Some(MintedOp::new(Minter::Cli, OP))) + .expect("replayed dial"); assert!(!replay.applied_now, "replay is deduped, not re-dialed"); assert_eq!( replay.conn_id, first.conn_id, @@ -312,7 +316,10 @@ fn dial_to_a_black_holing_peer_fails_with_a_bounded_ordinary_error() { // Re-driving the SAME durable op still ATTEMPTS (errors again) rather than // dedup-succeeding into a phantom — the un-applied key means a clean retry. brain_a - .net_dial(brain_b.net_status().expect("b status").addr, Some(MintedOp::new(Minter::Cli, OP))) + .net_dial( + brain_b.net_status().expect("b status").addr, + Some(MintedOp::new(Minter::Cli, OP)), + ) .expect_err("the un-applied op re-dials (re-times-out), never a phantom dedup"); } diff --git a/crates/spt-daemon/tests/netstream.rs b/crates/spt-daemon/tests/netstream.rs index 05694b83..d490e3c2 100644 --- a/crates/spt-daemon/tests/netstream.rs +++ b/crates/spt-daemon/tests/netstream.rs @@ -21,7 +21,7 @@ use std::thread; use std::time::Duration; use spt_daemon::brain::{Brain, BrokerEvent}; -use spt_daemon::effect::{EffectKey, Minter, MintedOp}; +use spt_daemon::effect::{EffectKey, MintedOp, Minter}; use spt_daemon::nethost::{NetConfig, NetHost, NET_EFFECT_SESSION}; use spt_daemon::Broker; use spt_net::net::endpoint::{BindScope, LocalDiscovery, RelayPolicy}; @@ -155,11 +155,20 @@ fn receiver_brain_restart_is_gapless_and_exactly_once() { let mut sender = connect_retry(&name_a); let mut b_probe = connect_retry(&name_b); let addr = b_probe.net_status().expect("b status").addr; - let conn = sender.net_dial(addr, Some(MintedOp::new(Minter::Cli, 1))).expect("dial"); - let opened = sender.net_open_stream(conn.conn_id, Some(MintedOp::new(Minter::Cli, 2))).expect("open"); + let conn = sender + .net_dial(addr, Some(MintedOp::new(Minter::Cli, 1))) + .expect("dial"); + let opened = sender + .net_open_stream(conn.conn_id, Some(MintedOp::new(Minter::Cli, 2))) + .expect("open"); for n in 0..KILL_AT { sender - .net_stream_send(opened.stream_id, &chunk_for(n), Some(MintedOp::new(Minter::Cli, 100 + n)), false) + .net_stream_send( + opened.stream_id, + &chunk_for(n), + Some(MintedOp::new(Minter::Cli, 100 + n)), + false, + ) .expect("send"); } @@ -182,11 +191,21 @@ fn receiver_brain_restart_is_gapless_and_exactly_once() { // broker-owned conn/stream are untouched by the receiver's brain death. for n in KILL_AT..TOTAL { sender - .net_stream_send(opened.stream_id, &chunk_for(n), Some(MintedOp::new(Minter::Cli, 100 + n)), false) + .net_stream_send( + opened.stream_id, + &chunk_for(n), + Some(MintedOp::new(Minter::Cli, 100 + n)), + false, + ) .expect("send into the dead window"); } sender - .net_stream_send(opened.stream_id, &[], Some(MintedOp::new(Minter::Cli, 100 + TOTAL)), true) + .net_stream_send( + opened.stream_id, + &[], + Some(MintedOp::new(Minter::Cli, 100 + TOTAL)), + true, + ) .expect("finish"); // Receiver life 2: re-attach, resubscribe from the durable cursor — the @@ -232,18 +251,29 @@ fn sender_brain_restart_redrive_is_exactly_once() { // Sender life 1: dial(1) + open(2) + sends 100..100+CRASH_AFTER, then crash. let mut life1 = connect_retry(&name_a); - let conn = life1.net_dial(addr.clone(), Some(MintedOp::new(Minter::Cli, 1))).expect("dial"); - let opened1 = life1.net_open_stream(conn.conn_id, Some(MintedOp::new(Minter::Cli, 2))).expect("open"); + let conn = life1 + .net_dial(addr.clone(), Some(MintedOp::new(Minter::Cli, 1))) + .expect("dial"); + let opened1 = life1 + .net_open_stream(conn.conn_id, Some(MintedOp::new(Minter::Cli, 2))) + .expect("open"); for n in 0..CRASH_AFTER { life1 - .net_stream_send(opened1.stream_id, &chunk_for(n), Some(MintedOp::new(Minter::Cli, 100 + n)), false) + .net_stream_send( + opened1.stream_id, + &chunk_for(n), + Some(MintedOp::new(Minter::Cli, 100 + n)), + false, + ) .expect("send"); } drop(life1); // crash before retiring anything from the durable source // Sender life 2: re-drive the WHOLE durable sequence with the same op ids. let mut life2 = connect_retry(&name_a); - let conn2 = life2.net_dial(addr, Some(MintedOp::new(Minter::Cli, 1))).expect("redial"); + let conn2 = life2 + .net_dial(addr, Some(MintedOp::new(Minter::Cli, 1))) + .expect("redial"); assert!(!conn2.applied_now, "dial replay deduped"); assert_eq!( conn2.conn_id, conn.conn_id, @@ -260,7 +290,12 @@ fn sender_brain_restart_redrive_is_exactly_once() { let mut deduped = 0; for n in 0..TOTAL { let ack = life2 - .net_stream_send(opened2.stream_id, &chunk_for(n), Some(MintedOp::new(Minter::Cli, 100 + n)), false) + .net_stream_send( + opened2.stream_id, + &chunk_for(n), + Some(MintedOp::new(Minter::Cli, 100 + n)), + false, + ) .expect("re-driven send") .expect("acked"); if !ack.applied_now { @@ -272,7 +307,12 @@ fn sender_brain_restart_redrive_is_exactly_once() { "exactly the pre-crash sends dedup" ); life2 - .net_stream_send(opened2.stream_id, &[], Some(MintedOp::new(Minter::Cli, 100 + TOTAL)), true) + .net_stream_send( + opened2.stream_id, + &[], + Some(MintedOp::new(Minter::Cli, 100 + TOTAL)), + true, + ) .expect("finish"); // The journal holds each net op exactly once. diff --git a/crates/spt-daemon/tests/notif_drain_validity.rs b/crates/spt-daemon/tests/notif_drain_validity.rs index 9495ae26..06ce3fb0 100644 --- a/crates/spt-daemon/tests/notif_drain_validity.rs +++ b/crates/spt-daemon/tests/notif_drain_validity.rs @@ -61,7 +61,14 @@ fn surface_to_a_busy_endpoint(id: &str) -> (std::path::PathBuf, String) { let store = NotifStore::open().expect("notif store"); let mut epochs = EpochSource::load(); let row = store - .produce("beef", &mut epochs, "home", "update", "doyle", "update available: v0.41.0") + .produce( + "beef", + &mut epochs, + "home", + "update", + "doyle", + "update available: v0.41.0", + ) .expect("produce the notif row"); // The quiet-delivery copy: the composed notify envelope, spooled active_only. @@ -108,7 +115,10 @@ fn a_dismissed_rows_spooled_copy_delivers_nothing() { // The apply seam dismisses the ROW — the copy in the spool is untouched by // that (it is a detached snapshot), which is the whole defect. let store = NotifStore::open().expect("notif store"); - assert!(store.dismiss(¬if_id).expect("dismiss"), "the row was dismissed"); + assert!( + store.dismiss(¬if_id).expect("dismiss"), + "the row was dismissed" + ); assert_eq!( spool::pending_count_at(&perch).unwrap(), 1, diff --git a/crates/spt-daemon/tests/notif_quiet_delivery.rs b/crates/spt-daemon/tests/notif_quiet_delivery.rs index 263cf070..b57eef89 100644 --- a/crates/spt-daemon/tests/notif_quiet_delivery.rs +++ b/crates/spt-daemon/tests/notif_quiet_delivery.rs @@ -113,7 +113,7 @@ fn notif_first_fire_is_quiet_even_to_a_live_relay_rollback_included() { &owlery, 2_000, ) - .expect("produce rollback notif"); + .expect("produce rollback notif"); assert!( matches!( rb_fired, diff --git a/crates/spt-daemon/tests/notifsync.rs b/crates/spt-daemon/tests/notifsync.rs index df39bf67..3c0eea2a 100644 --- a/crates/spt-daemon/tests/notifsync.rs +++ b/crates/spt-daemon/tests/notifsync.rs @@ -21,7 +21,7 @@ use std::thread; use std::time::Duration; use spt_daemon::brain::{Brain, BrokerEvent}; -use spt_daemon::effect::{Minter, MintedOp}; +use spt_daemon::effect::{MintedOp, Minter}; use spt_daemon::nethost::{NetConfig, NetHost}; use spt_daemon::notifsync::{apply_notif_feed, emit_notif_feed, NotifApplyVerdict, NotifPolicy}; use spt_daemon::Broker; @@ -175,8 +175,12 @@ fn notif_spools_converge_over_the_wire_and_dismiss_replicates() { .node_id_hex .expect("node id"); let addr = b_probe.net_status().expect("b status").addr; - let conn = sender.net_dial(addr, Some(MintedOp::new(Minter::Cli, 1))).expect("dial"); - let opened = sender.net_open_stream(conn.conn_id, Some(MintedOp::new(Minter::Cli, 2))).expect("open"); + let conn = sender + .net_dial(addr, Some(MintedOp::new(Minter::Cli, 1))) + .expect("dial"); + let opened = sender + .net_open_stream(conn.conn_id, Some(MintedOp::new(Minter::Cli, 2))) + .expect("open"); let wire = emit_notif_feed(&store_a, "home").expect("emit"); let split = wire.len() / 2; @@ -256,7 +260,10 @@ fn notif_spools_converge_over_the_wire_and_dismiss_replicates() { .map(|s| s.stream_id) .collect(); let conn_back = b_probe - .net_dial(sender.net_status().expect("a").addr, Some(MintedOp::new(Minter::Cli, 3))) + .net_dial( + sender.net_status().expect("a").addr, + Some(MintedOp::new(Minter::Cli, 3)), + ) .expect("dial back"); let opened_back = b_probe .net_open_stream(conn_back.conn_id, Some(MintedOp::new(Minter::Cli, 4))) @@ -350,8 +357,15 @@ fn node_scoped_stays_home_and_migration_dismissal_reaches_the_peer() { // as a pre-0046 peer would still carry it). let node_row = store_a .produce_scoped( - &a_node, &mut epochs, "home", "consent", "spt-update", "staged", - NotifScope::Node, Some("spt-core:update-staged"), None, + &a_node, + &mut epochs, + "home", + "consent", + "spt-update", + "staged", + NotifScope::Node, + Some("spt-core:update-staged"), + None, ) .unwrap(); let subnet_row = store_a @@ -359,8 +373,15 @@ fn node_scoped_stays_home_and_migration_dismissal_reaches_the_peer() { .unwrap(); let stale_update = store_a .produce_scoped( - &a_node, &mut epochs, "home", "consent", "spt-update", "old prompt", - NotifScope::Subnet, None, None, + &a_node, + &mut epochs, + "home", + "consent", + "spt-update", + "old prompt", + NotifScope::Subnet, + None, + None, ) .unwrap(); @@ -386,21 +407,41 @@ fn node_scoped_stays_home_and_migration_dismissal_reaches_the_peer() { store_b.get(&node_row.notif_id).unwrap().is_none(), "peer never materializes the node-scoped row" ); - assert!(!store_b.get(&stale_update.notif_id).unwrap().unwrap().dismissed); + assert!( + !store_b + .get(&stale_update.notif_id) + .unwrap() + .unwrap() + .dismissed + ); // A upgrades and runs the one-shot migration: every spt-update consent row // is auto-dismissed locally — both the stale subnet row AND the node-scoped // one (both carry from_id=spt-update, kind=consent). The node row's // dismissal stays home (never feeds); the subnet row's replicates. - assert_eq!(store_a.dismiss_stale_update_rows().unwrap(), 2, "both spt-update consent rows"); + assert_eq!( + store_a.dismiss_stale_update_rows().unwrap(), + 2, + "both spt-update consent rows" + ); // Feed 2: the dismissal replicates — B's copy latches dismissed. let records2 = feed_over_wire(&mut sender, &mut b_probe, &store_a, "home", 3, 4); apply_notif_feed(&store_b, &a_node, &records2, &policy_b).expect("apply 2"); assert!( - store_b.get(&stale_update.notif_id).unwrap().unwrap().dismissed, + store_b + .get(&stale_update.notif_id) + .unwrap() + .unwrap() + .dismissed, "migration dismissal reached the not-yet-upgraded peer" ); // The migration left the agent row untouched. - assert!(!store_b.get(&subnet_row.notif_id).unwrap().unwrap().dismissed); + assert!( + !store_b + .get(&subnet_row.notif_id) + .unwrap() + .unwrap() + .dismissed + ); } diff --git a/crates/spt-daemon/tests/propagate.rs b/crates/spt-daemon/tests/propagate.rs index 7a4c886b..4715eeb8 100644 --- a/crates/spt-daemon/tests/propagate.rs +++ b/crates/spt-daemon/tests/propagate.rs @@ -15,26 +15,24 @@ use std::thread; use std::time::Duration; use ed25519_dalek::{Signer, SigningKey}; +use spt_daemon::effect::{MintedOp, Minter}; use spt_daemon::nethost::{NetConfig, NetHost}; use spt_daemon::propagate::{ classify_status, request_update, request_update_status, serve_update, ConvergeState, UpdatePullOutcome, UpdateServeOutcome, UpdateStatusReport, }; -use spt_daemon::effect::{Minter, MintedOp}; use spt_daemon::relcache::ReleaseCache; -use spt_store::epoch::EpochSource; -use spt_store::notif::{NotifScope, NotifStore}; use spt_daemon::release::{ current_platform, RejectReason, ReleaseMetadata, SignedRelease, SignedUpdateSet, UpdateArtifactMetadata, UpdateSetMetadata, VerifyPolicy, }; -use spt_daemon::update::{ - plan_verified_update_set, BrokerAbi, UpdateClass, BROKER_RESOURCE_ABI, -}; +use spt_daemon::update::{plan_verified_update_set, BrokerAbi, UpdateClass, BROKER_RESOURCE_ABI}; use spt_daemon::{Brain, Broker}; use spt_net::net::endpoint::{BindScope, LocalDiscovery, RelayPolicy}; use spt_net::net::update::UpdRecord; use spt_proto::identity::Identity; +use spt_store::epoch::EpochSource; +use spt_store::notif::{NotifScope, NotifStore}; use spt_store::roster::{RosterEntry, RosterStore}; use std::collections::{BTreeMap, BTreeSet}; @@ -226,9 +224,14 @@ fn update_set_carries_and_verifies_the_musl_artifact() { // A musl node fetches + verifies its OWN artifact — the W3 field gap closed // (before W3 a musl node hit NoArtifactForPlatform: no release carried musl). - let musl_plan = - plan_verified_update_set(&running, &signed, "x86_64-unknown-linux-musl", musl_bytes, &pol) - .expect("musl artifact must select + verify — no NoArtifactForPlatform"); + let musl_plan = plan_verified_update_set( + &running, + &signed, + "x86_64-unknown-linux-musl", + musl_bytes, + &pol, + ) + .expect("musl artifact must select + verify — no NoArtifactForPlatform"); assert_eq!(musl_plan.class, UpdateClass::BrainOnly); // The signature covers the musl bytes: tampered musl bytes are rejected. @@ -245,9 +248,14 @@ fn update_set_carries_and_verifies_the_musl_artifact() { ); // gnu default-Linux path unchanged: a gnu node still selects the gnu artifact. - let gnu_plan = - plan_verified_update_set(&running, &signed, "x86_64-unknown-linux-gnu", gnu_bytes, &pol) - .expect("gnu artifact still selects + verifies"); + let gnu_plan = plan_verified_update_set( + &running, + &signed, + "x86_64-unknown-linux-gnu", + gnu_bytes, + &pol, + ) + .expect("gnu artifact still selects + verifies"); assert_eq!(gnu_plan.class, UpdateClass::BrainOnly); // Selection stays exact: a platform absent from the set is rejected loudly. @@ -337,7 +345,9 @@ fn pull( .collect(); let mut req_brain = connect_retry(&requester.name); - let conn = req_brain.net_dial(addr, Some(MintedOp::new(Minter::Cli, op()))).expect("dial"); + let conn = req_brain + .net_dial(addr, Some(MintedOp::new(Minter::Cli, op()))) + .expect("dial"); let open_op = op(); let running = BrokerAbi::current(); let req_cache = requester.cache.clone(); @@ -557,7 +567,9 @@ fn rollback_offer_is_rejected_before_any_fetch() { .collect(); let mut req_brain = connect_retry(&v.name); - let conn = req_brain.net_dial(addr, Some(MintedOp::new(Minter::Cli, op()))).expect("dial"); + let conn = req_brain + .net_dial(addr, Some(MintedOp::new(Minter::Cli, op()))) + .expect("dial"); let open_op = op(); let running = BrokerAbi::current(); let pol = policy(5); @@ -644,7 +656,9 @@ fn status_pull( .collect(); let mut req_brain = connect_retry(&requester.name); - let conn = req_brain.net_dial(addr, Some(MintedOp::new(Minter::Cli, op()))).expect("dial"); + let conn = req_brain + .net_dial(addr, Some(MintedOp::new(Minter::Cli, op()))) + .expect("dial"); let asker = thread::spawn(move || request_update_status(&mut req_brain, conn.conn_id)); let (stream, origin) = wait_for_stream_except(&mut serve_brain, &skip); @@ -834,9 +848,15 @@ fn signed_release_pv(version: u64, artifact: &[u8], product_version: &str) -> Si fn stage_notif(store: &NotifStore, epochs: &mut EpochSource) -> String { store .produce_scoped( - "cafe", epochs, "home", "consent", "spt-update", - "An spt-core update is available", NotifScope::Node, - Some("spt-core:update-staged"), None, + "cafe", + epochs, + "home", + "consent", + "spt-update", + "An spt-core update is available", + NotifScope::Node, + Some("spt-core:update-staged"), + None, ) .expect("produce update-staged notif") .notif_id @@ -861,17 +881,25 @@ fn worker_dismisses_the_staged_notif_when_the_running_image_catches_up() { // ── IN-BAND leg: applied-version counter. ─────────────────────────────── let cache = ReleaseCache::open(&dir.path().join("in-band")); - cache.stage(&signed_release(6, &artifact), &artifact).expect("stage v6"); + cache + .stage(&signed_release(6, &artifact), &artifact) + .expect("stage v6"); let store = NotifStore::open_at(&dir.path().join("in-band-notifs.db")).expect("store"); let mut epochs = EpochSource::load_from(&dir.path().join("in-band-epoch")); let id = stage_notif(&store, &mut epochs); // No applied record, empty product_version → neither signal fires → live. spt_daemon::pump::dismiss_staged_notif_if_caught_up(&cache, &store, "home"); - assert!(!store.get(&id).unwrap().unwrap().dismissed, "behind → stays live"); + assert!( + !store.get(&id).unwrap().unwrap().dismissed, + "behind → stays live" + ); // Recorded apply catches the counter up → dismissed by key. cache.record_applied(6).expect("record applied"); spt_daemon::pump::dismiss_staged_notif_if_caught_up(&cache, &store, "home"); - assert!(store.get(&id).unwrap().unwrap().dismissed, "in-band applied → dismissed"); + assert!( + store.get(&id).unwrap().unwrap().dismissed, + "in-band applied → dismissed" + ); // ── OUT-OF-BAND leg: running image vs staged product_version, applied // record ABSENT throughout. ──────────────────────────────────────────── @@ -884,7 +912,11 @@ fn worker_dismisses_the_staged_notif_when_the_running_image_catches_up() { let store_p = NotifStore::open_at(&dir.path().join("oob-past-notifs.db")).expect("store"); let mut ep_p = EpochSource::load_from(&dir.path().join("oob-past-epoch")); let id_p = stage_notif(&store_p, &mut ep_p); - assert_eq!(cache_past.applied_version(), None, "no applied record — out of band"); + assert_eq!( + cache_past.applied_version(), + None, + "no applied record — out of band" + ); spt_daemon::pump::dismiss_staged_notif_if_caught_up(&cache_past, &store_p, "home"); assert!( store_p.get(&id_p).unwrap().unwrap().dismissed, diff --git a/crates/spt-daemon/tests/psyche_context_file_e2e.rs b/crates/spt-daemon/tests/psyche_context_file_e2e.rs index af0a5348..3162895e 100644 --- a/crates/spt-daemon/tests/psyche_context_file_e2e.rs +++ b/crates/spt-daemon/tests/psyche_context_file_e2e.rs @@ -110,7 +110,13 @@ fn proof_manifest_toml(resume_cmd: &str) -> String { fn seed_bound_perch(id: &str, session_id: &str) { let path = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&path).unwrap(); - let mut rec = InfoJson::new(id, "2026-06-01T00:00:00Z", std::process::id(), session_id, "live_agent"); + let mut rec = InfoJson::new( + id, + "2026-06-01T00:00:00Z", + std::process::id(), + session_id, + "live_agent", + ); rec.status = Some(STATUS_ONLINE.to_string()); rec.controllable = Some(true); info::write_info(&path, &rec).unwrap(); diff --git a/crates/spt-daemon/tests/psyche_event_turn_e2e.rs b/crates/spt-daemon/tests/psyche_event_turn_e2e.rs index 9da2eec7..f2c3abde 100644 --- a/crates/spt-daemon/tests/psyche_event_turn_e2e.rs +++ b/crates/spt-daemon/tests/psyche_event_turn_e2e.rs @@ -133,8 +133,7 @@ fn pulse_fire_runs_one_bounded_psyche_turn() { // ephemeral model does not). This is the structural "no resident" discriminator // (`is_perch_alive` reads an ABSENT perch as alive — interim parity — so it is // NOT the probe here). - let psyche_perch = - perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); + let psyche_perch = perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); assert!( !psyche_perch.join("info.json").exists(), "no {{id}}-psyche perch is bound by a per-event turn (RED if a resident spawn is re-added)" @@ -164,7 +163,8 @@ fn host_one_spawns_no_resident_psyche() { // An online live_agent perch with the adapter set — reconcile hosts it. let perch_path = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&perch_path).unwrap(); - let mut rec = spt_store::info::InfoJson::new(id, "t", std::process::id(), "sid-1", "live_agent"); + let mut rec = + spt_store::info::InfoJson::new(id, "t", std::process::id(), "sid-1", "live_agent"); rec.adapter = Some("mock".to_string()); spt_store::info::write_info(&perch_path, &rec).unwrap(); spt_store::info::set_status(&perch_path, STATUS_ONLINE).unwrap(); @@ -184,16 +184,20 @@ fn host_one_spawns_no_resident_psyche() { &cfg, StartReason::Cold, ); - assert_eq!(set.len(), 1, "the online live endpoint is hosted (pulse loop started)"); + assert_eq!( + set.len(), + 1, + "the online live endpoint is hosted (pulse loop started)" + ); // The host spawned NO resident psyche: the nested perch is never a live process. // (RED if host_one re-adds the retired spawn_psyche_owned resident spawn.) - let psyche_perch = - perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); + let psyche_perch = perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); // Give any (erroneously re-added) resident spawn a moment to bind its perch, then // assert none was bound (info.json absent = no resident — see leg 1's note). - let never_resident = - !wait_until(Duration::from_secs(2), || psyche_perch.join("info.json").exists()); + let never_resident = !wait_until(Duration::from_secs(2), || { + psyche_perch.join("info.json").exists() + }); // Tear down the driver thread via the public un-host path (flip offline → // reconcile un-hosts + joins) so the tempdir cleanup does not race a live loop. diff --git a/crates/spt-daemon/tests/psyche_residency_expectation_e2e.rs b/crates/spt-daemon/tests/psyche_residency_expectation_e2e.rs index c03dfd07..4ad9180b 100644 --- a/crates/spt-daemon/tests/psyche_residency_expectation_e2e.rs +++ b/crates/spt-daemon/tests/psyche_residency_expectation_e2e.rs @@ -129,8 +129,12 @@ fn failing_psyche_never_unhosts_or_destamps_the_parent() { // MULTI-SUBNET home (the hall-bf field trigger: ≥2 subnets, one node). { let mut store = spt_store::subnet::SubnetStore::load(); - store.create_subnet("home-a", spt_store::access::Mode::Open).expect("seed subnet a"); - store.create_subnet("home-b", spt_store::access::Mode::Open).expect("seed subnet b"); + store + .create_subnet("home-a", spt_store::access::Mode::Open) + .expect("seed subnet a"); + store + .create_subnet("home-b", spt_store::access::Mode::Open) + .expect("seed subnet b"); store.save().expect("save subnets"); } @@ -177,7 +181,11 @@ fn failing_psyche_never_unhosts_or_destamps_the_parent() { ) }; run_reconcile(); - assert_eq!(set.len(), 1, "the online live endpoint is hosted (pulse driver started)"); + assert_eq!( + set.len(), + 1, + "the online live endpoint is hosted (pulse driver started)" + ); // Drive the failing turns: re-arm the echo gate repeatedly (the driver consumes it // each fire), until several turns have fired AND the fault stamp has landed. @@ -214,7 +222,10 @@ fn failing_psyche_never_unhosts_or_destamps_the_parent() { ); // The budget stamped the fault on the PARENT — psyche fields only. - assert!(stamped, "the turn-failure budget must stamp psyche_host_error on the parent"); + assert!( + stamped, + "the turn-failure budget must stamp psyche_host_error on the parent" + ); let info = spt_store::info::read_info(&perch_path).expect("parent perch readable"); assert!( info.psyche_host_error.is_some(), @@ -234,7 +245,11 @@ fn failing_psyche_never_unhosts_or_destamps_the_parent() { // (1) still HOSTED (no un-host churn), (2) still ONLINE (deliverable), (3) ready // marker still PRESENT. A resident-model teardown (the deleted v0.13.2 shape) would // fail all three — that is the RED-first guard-revert. - assert_eq!(set.len(), 1, "the endpoint is NOT un-hosted (no rehost churn)"); + assert_eq!( + set.len(), + 1, + "the endpoint is NOT un-hosted (no rehost churn)" + ); assert_eq!( info.status.as_deref(), Some(STATUS_ONLINE), @@ -250,7 +265,10 @@ fn failing_psyche_never_unhosts_or_destamps_the_parent() { // FAILING PSYCHE never triggered it above). spt_store::info::set_status(&perch_path, spt_store::liveness::STATUS_OFFLINE).unwrap(); run_reconcile(); - assert!(set.is_empty(), "an offline-transitioned endpoint IS un-hosted (the legit path)"); + assert!( + set.is_empty(), + "an offline-transitioned endpoint IS un-hosted (the legit path)" + ); std::env::remove_var("SPT_PSYCHE_TURN_STRIKE_BUDGET"); } diff --git a/crates/spt-daemon/tests/pump.rs b/crates/spt-daemon/tests/pump.rs index eb80b9b4..86934300 100644 --- a/crates/spt-daemon/tests/pump.rs +++ b/crates/spt-daemon/tests/pump.rs @@ -171,7 +171,9 @@ fn pump_and_dispatch_self_drive_the_subnet() { // ── B (canonical home): gates + the mind A will bootstrap-pull. ────── let mut subnets = SubnetStore::load(); - subnets.create_subnet(subnet, spt_store::access::Mode::Open).expect("create subnet"); + subnets + .create_subnet(subnet, spt_store::access::Mode::Open) + .expect("create subnet"); subnets.save().expect("save subnets"); // Mesh-D6: membership is the roster — B rosters A (both the inbound gate and // the pump's push target read it). Seed the canonical roster. @@ -279,7 +281,9 @@ fn pump_and_dispatch_self_drive_the_subnet() { info::write_info(&perch_path, &rec).unwrap(); let mut a_subnets = SubnetStore::default(); - a_subnets.create_subnet(subnet, spt_store::access::Mode::Open).expect("A subnet"); + a_subnets + .create_subnet(subnet, spt_store::access::Mode::Open) + .expect("A subnet"); a_subnets.save_to(&a_paths.subnets).expect("save A subnets"); // Mesh-D6: A's membership IS the roster — both its inbound gates and its // pump push target read it. The pump derives the roster path as a sibling of @@ -533,7 +537,9 @@ fn pump_survives_a_black_holing_peer_heartbeat_advances_no_restart() { let a_root = dir.path().join("a"); std::fs::create_dir_all(&a_root).unwrap(); let mut a_subnets = SubnetStore::default(); - a_subnets.create_subnet(subnet, spt_store::access::Mode::Open).expect("A subnet"); + a_subnets + .create_subnet(subnet, spt_store::access::Mode::Open) + .expect("A subnet"); a_subnets .save_to(&a_root.join("subnet.json")) .expect("save subnets"); @@ -725,7 +731,9 @@ fn pump_w2_live_peer_advertised_amid_dead_peers_no_restart() { let a_root = dir.path().join("a"); std::fs::create_dir_all(&a_root).unwrap(); let mut a_subnets = SubnetStore::default(); - a_subnets.create_subnet(subnet, spt_store::access::Mode::Open).expect("subnet"); + a_subnets + .create_subnet(subnet, spt_store::access::Mode::Open) + .expect("subnet"); a_subnets .save_to(&a_root.join("subnet.json")) .expect("save subnets"); @@ -815,10 +823,10 @@ fn pump_w2_live_peer_advertised_amid_dead_peers_no_restart() { converge( "this node advertised to the live peer in the same round", || { - live_probe - .net_streams() - .map(|r| r.streams.iter().any(|s| s.remote_id_hex == a_hex)) - .unwrap_or(false) + live_probe + .net_streams() + .map(|r| r.streams.iter().any(|s| s.remote_id_hex == a_hex)) + .unwrap_or(false) }, ); diff --git a/crates/spt-daemon/tests/pumpdeadline.rs b/crates/spt-daemon/tests/pumpdeadline.rs index 2ed39ab0..e97fb29b 100644 --- a/crates/spt-daemon/tests/pumpdeadline.rs +++ b/crates/spt-daemon/tests/pumpdeadline.rs @@ -18,8 +18,8 @@ use std::time::{Duration, Instant}; use spt_daemon::brain::Brain; use spt_daemon::codec::read_frame; -use spt_daemon::transport::{recv_hello, DaemonTransport, LocalSocketTransport}; use spt_daemon::frame::Role; +use spt_daemon::transport::{recv_hello, DaemonTransport, LocalSocketTransport}; static SEQ: AtomicU32 = AtomicU32::new(0); fn unique_name() -> String { @@ -58,8 +58,8 @@ fn pump_brain_times_out_when_broker_never_replies() { // then drop it (unblocking the client's reader thread to exit cleanly). thread::sleep(timeout * 3); }); - let mut brain = - Brain::cold_start_pump(&name, 0, timeout, spt_daemon::brain::PumpTrace::Stderr).expect("connect pump-mode brain"); + let mut brain = Brain::cold_start_pump(&name, 0, timeout, spt_daemon::brain::PumpTrace::Stderr) + .expect("connect pump-mode brain"); let started = Instant::now(); let err = brain @@ -148,8 +148,8 @@ fn pump_reply_read_reclassifies_a_silent_peer_within_the_budget() { recv_hello(&mut conn, Role::Brain).expect("hello handshake"); thread::sleep(timeout * 3); }); - let mut brain = - Brain::cold_start_pump(&name, 0, timeout, spt_daemon::brain::PumpTrace::Stderr).expect("connect pump-mode brain"); + let mut brain = Brain::cold_start_pump(&name, 0, timeout, spt_daemon::brain::PumpTrace::Stderr) + .expect("connect pump-mode brain"); // reply_read_deadline = now + min(io_timeout, 10s) = the 200ms test budget. let deadline = brain.reply_read_deadline(); diff --git a/crates/spt-daemon/tests/redispatch_stall.rs b/crates/spt-daemon/tests/redispatch_stall.rs index d2e6a93b..e9afa1eb 100644 --- a/crates/spt-daemon/tests/redispatch_stall.rs +++ b/crates/spt-daemon/tests/redispatch_stall.rs @@ -520,7 +520,7 @@ fn poisoned_subscriber_cancels_the_paired_forwarding_leg_then_recovery_serves() Ok(_) => break true, Err(e) if e.to_string().contains("lease canceled") - || e.to_string().contains("subscriber busy") => + || e.to_string().contains("subscriber busy") => { thread::sleep(Duration::from_millis(300)); } diff --git a/crates/spt-daemon/tests/registry_lifecycle.rs b/crates/spt-daemon/tests/registry_lifecycle.rs index f7559d27..45265bc9 100644 --- a/crates/spt-daemon/tests/registry_lifecycle.rs +++ b/crates/spt-daemon/tests/registry_lifecycle.rs @@ -200,7 +200,9 @@ fn oneway_rounds_plateau_rows_seats_and_a_refresh_replays_nothing() { // ── B (canonical home): subnet + roster trusting A + a mind for the // sync leg (the cross-family exchange on the same carrier). ───────── let mut subnets = SubnetStore::load(); - subnets.create_subnet(subnet, spt_store::access::Mode::Open).expect("create subnet"); + subnets + .create_subnet(subnet, spt_store::access::Mode::Open) + .expect("create subnet"); subnets.save().expect("save subnets"); let mut roster = spt_store::roster::RosterStore::load(); roster.merge_entry(roster_entry(&a_hex, subnet)); @@ -248,7 +250,9 @@ fn oneway_rounds_plateau_rows_seats_and_a_refresh_replays_nothing() { info::write_info(&perch_path, &rec).unwrap(); let mut a_subnets = SubnetStore::default(); - a_subnets.create_subnet(subnet, spt_store::access::Mode::Open).expect("A subnet"); + a_subnets + .create_subnet(subnet, spt_store::access::Mode::Open) + .expect("A subnet"); a_subnets.save_to(&a_paths.subnets).expect("save A subnets"); let mut a_roster = spt_store::roster::RosterStore::default(); a_roster.merge_entry(roster_entry(&b_hex, subnet)); @@ -448,43 +452,43 @@ fn oneway_rounds_plateau_rows_seats_and_a_refresh_replays_nothing() { // direction — more time only gives a replaying gen-2 more chance to be // CAUGHT, so a slow box cannot manufacture a false pass. thread::sleep(Duration::from_millis(1500)); // ~60 polls of the fresh generation - // A STORM BOUND, not an equality — and the distinction is load-bearing. - // - // This assertion used to be `== writes_before`, and it was INVALID rather - // than merely flaky: `snapshot_write_count` is a GLOBAL counter on B's - // registry, so it charges to gen-2 any write from ANY source landing in - // this window. Proven by experiment, not inferred — with gen-2 NEVER - // STARTED the equality still failed 8 of 15 runs, and `writes_before` - // itself is nondeterministic run to run (observed 6 and 7) because the - // pump's own late work can land either side of the sample. A claim keyed - // on a proxy (total writes on the box) instead of on its subject (writes - // CAUSED BY gen-2). - // - // WHAT THIS CAN AND CANNOT DO, stated plainly so nobody re-tightens it: - // it catches a replay STORM — the v0.34/v0.36 regression re-applied ~4361 - // rows per generation, and here a storm would re-apply the whole history, - // roughly DOUBLING the count. It CANNOT attribute a single write to a - // generation. Exact attribution needs per-generation write accounting, - // which does not exist yet (seeded separately) — and the rig cannot - // manufacture it, because the PRODUCT has no generation boundary to - // observe: `run_dispatch_loop` returns while its spawned workers are still - // applying, so gen-1's writes can land after gen-2 has started. - // - // The bound is derived from the rig's own scale rather than hardcoded: a - // storm re-applies the history the pump built, so that history IS the - // storm's size. - // - // NO PRECONDITION FLOOR on the history size, and the reason is structural - // rather than a tolerance: this bound gets STRICTER as the history shrinks, - // not weaker. A storm re-applies the whole history, so it adds ~scale - // writes while the bound permits scale/2 — the storm is caught for ANY - // scale >= 1, and at scale 0 the bound demands growth 0 outright. Vacuity - // would come from a LARGE scale (which permits proportionally more), never - // a small one. An earlier draft guarded `scale >= 4` because the observed - // values happened to run 4-7; that was a threshold keyed on a MEASUREMENT - // rather than on the thing, it protected the direction that was never at - // risk, and on a slow box it would have produced a confusing red from the - // guard itself. + // A STORM BOUND, not an equality — and the distinction is load-bearing. + // + // This assertion used to be `== writes_before`, and it was INVALID rather + // than merely flaky: `snapshot_write_count` is a GLOBAL counter on B's + // registry, so it charges to gen-2 any write from ANY source landing in + // this window. Proven by experiment, not inferred — with gen-2 NEVER + // STARTED the equality still failed 8 of 15 runs, and `writes_before` + // itself is nondeterministic run to run (observed 6 and 7) because the + // pump's own late work can land either side of the sample. A claim keyed + // on a proxy (total writes on the box) instead of on its subject (writes + // CAUSED BY gen-2). + // + // WHAT THIS CAN AND CANNOT DO, stated plainly so nobody re-tightens it: + // it catches a replay STORM — the v0.34/v0.36 regression re-applied ~4361 + // rows per generation, and here a storm would re-apply the whole history, + // roughly DOUBLING the count. It CANNOT attribute a single write to a + // generation. Exact attribution needs per-generation write accounting, + // which does not exist yet (seeded separately) — and the rig cannot + // manufacture it, because the PRODUCT has no generation boundary to + // observe: `run_dispatch_loop` returns while its spawned workers are still + // applying, so gen-1's writes can land after gen-2 has started. + // + // The bound is derived from the rig's own scale rather than hardcoded: a + // storm re-applies the history the pump built, so that history IS the + // storm's size. + // + // NO PRECONDITION FLOOR on the history size, and the reason is structural + // rather than a tolerance: this bound gets STRICTER as the history shrinks, + // not weaker. A storm re-applies the whole history, so it adds ~scale + // writes while the bound permits scale/2 — the storm is caught for ANY + // scale >= 1, and at scale 0 the bound demands growth 0 outright. Vacuity + // would come from a LARGE scale (which permits proportionally more), never + // a small one. An earlier draft guarded `scale >= 4` because the observed + // values happened to run 4-7; that was a threshold keyed on a MEASUREMENT + // rather than on the thing, it protected the direction that was never at + // risk, and on a slow box it would have produced a confusing red from the + // guard itself. let storm_scale = writes_before; let growth = b_registry.snapshot_write_count() - writes_before; assert!( @@ -553,7 +557,9 @@ fn multichunk_feed_applies_with_exactly_one_snapshot_write() { // B: subnet + roster trusting A (the dispatcher's fail-closed gate). let mut subnets = SubnetStore::load(); - subnets.create_subnet(subnet, spt_store::access::Mode::Open).expect("create subnet"); + subnets + .create_subnet(subnet, spt_store::access::Mode::Open) + .expect("create subnet"); subnets.save().expect("save subnets"); let mut roster = spt_store::roster::RosterStore::load(); roster.merge_entry(roster_entry(&a_hex, subnet)); @@ -662,7 +668,9 @@ fn poisoned_registry_replay_strikes_out_terminal_while_fresh_feeds_serve() { let b_addr = b_probe.net_status().expect("status").addr; let mut subnets = SubnetStore::load(); - subnets.create_subnet(subnet, spt_store::access::Mode::Open).expect("create subnet"); + subnets + .create_subnet(subnet, spt_store::access::Mode::Open) + .expect("create subnet"); subnets.save().expect("save subnets"); let mut roster = spt_store::roster::RosterStore::load(); roster.merge_entry(roster_entry(&a_hex, subnet)); diff --git a/crates/spt-daemon/tests/render_lifecycle.rs b/crates/spt-daemon/tests/render_lifecycle.rs index 9eaed19b..cc6f5c58 100644 --- a/crates/spt-daemon/tests/render_lifecycle.rs +++ b/crates/spt-daemon/tests/render_lifecycle.rs @@ -129,7 +129,10 @@ fn final_output_frame_precedes_exit_through_the_production_path() { from_seq: 0, intent: AttachIntent::Control, endpoint_id: None, - gen: 100, code: None, seal_ceremony: false, }); + gen: 100, + code: None, + seal_ceremony: false, + }); op.net_stream_send(opened.stream_id, &line, None, false) .expect("send Request"); op.net_stream_subscribe(opened.stream_id, 0) diff --git a/crates/spt-daemon/tests/replicate.rs b/crates/spt-daemon/tests/replicate.rs index 71184661..803187b6 100644 --- a/crates/spt-daemon/tests/replicate.rs +++ b/crates/spt-daemon/tests/replicate.rs @@ -21,7 +21,7 @@ use std::thread; use std::time::Duration; use spt_daemon::brain::{Brain, BrokerEvent}; -use spt_daemon::effect::{Minter, MintedOp}; +use spt_daemon::effect::{MintedOp, Minter}; use spt_daemon::nethost::{NetConfig, NetHost}; use spt_daemon::Broker; use spt_net::net::endpoint::{BindScope, LocalDiscovery, RelayPolicy}; @@ -174,18 +174,32 @@ fn registries_converge_over_the_wire_and_the_lease_holds() { // ── The wire: dial B, open a stream, send the feed (journaled ops). ───── let mut b_probe = connect_retry(&name_b); let addr = b_probe.net_status().expect("b status").addr; - let conn = sender.net_dial(addr, Some(MintedOp::new(Minter::Cli, 1))).expect("dial"); - let opened = sender.net_open_stream(conn.conn_id, Some(MintedOp::new(Minter::Cli, 2))).expect("open"); + let conn = sender + .net_dial(addr, Some(MintedOp::new(Minter::Cli, 1))) + .expect("dial"); + let opened = sender + .net_open_stream(conn.conn_id, Some(MintedOp::new(Minter::Cli, 2))) + .expect("open"); // Send 1: the Active row, split MID-RECORD across two separate sends — // the receiver's decoder, not QUIC chunk shape, owns record framing. let line = update_active.encode_line(); let split = line.len() / 2; sender - .net_stream_send(opened.stream_id, &line[..split], Some(MintedOp::new(Minter::Cli, 100)), false) + .net_stream_send( + opened.stream_id, + &line[..split], + Some(MintedOp::new(Minter::Cli, 100)), + false, + ) .expect("send first half"); sender - .net_stream_send(opened.stream_id, &line[split..], Some(MintedOp::new(Minter::Cli, 101)), false) + .net_stream_send( + opened.stream_id, + &line[split..], + Some(MintedOp::new(Minter::Cli, 101)), + false, + ) .expect("send second half"); // Send 2: the newer Offline. Send 3: the e1 Active REPLAYED (a lagging // duplicate arriving late) — the lease must drop it at B. diff --git a/crates/spt-daemon/tests/reseed.rs b/crates/spt-daemon/tests/reseed.rs index 07ea62c8..b476e971 100644 --- a/crates/spt-daemon/tests/reseed.rs +++ b/crates/spt-daemon/tests/reseed.rs @@ -14,9 +14,7 @@ use std::sync::{Arc, Mutex}; use std::time::Duration; use spt_daemon::nethost::{NetConfig, NetHost}; -use spt_daemon::seedproofx::{ - MemberStatus, MembershipSource, RosterExchange, SubnetCred, -}; +use spt_daemon::seedproofx::{MemberStatus, MembershipSource, RosterExchange, SubnetCred}; use spt_net::net::endpoint::{BindScope, LocalDiscovery, RelayPolicy}; use spt_proto::identity::Identity; @@ -61,7 +59,10 @@ fn grace_exchange(revoked: HashSet, adopted: Adopted) -> RosterExchange adopt_seed: Arc::new({ let adopted = adopted.clone(); move |subnet: &str, s: &[u8], epoch: u64| { - adopted.lock().unwrap().push((subnet.to_string(), s.to_vec(), epoch)); + adopted + .lock() + .unwrap() + .push((subnet.to_string(), s.to_vec(), epoch)); true } }), @@ -137,14 +138,24 @@ fn benign_offliner_is_reseeded_across_a_rotation() { "the offliner received a seed push" ); let pushed = b_adopt.lock().unwrap().clone(); - assert_eq!(pushed, vec![("home".to_string(), seed(2), 2)], "current seed adopted"); + assert_eq!( + pushed, + vec![("home".to_string(), seed(2), 2)], + "current seed adopted" + ); // A re-seeds, it does not pull one (it is the fresh side): nothing adopted. - assert!(a_adopt.lock().unwrap().is_empty(), "the fresh node adopts nothing"); + assert!( + a_adopt.lock().unwrap().is_empty(), + "the fresh node adopts nothing" + ); // A registered the conn only to deliver the seed — it is re-seed-only, so it // proves NO subnet (it serves nothing; it is replaced when B reconnects full). - assert!(wait_until(|| a.conn_count() == 1), "conn kept alive for delivery"); + assert!( + wait_until(|| a.conn_count() == 1), + "conn kept alive for delivery" + ); assert!( a.conn_proven_subnets(1).is_empty(), "a re-seed-only conn carries no proven subnet" @@ -189,7 +200,10 @@ fn grace_push_carries_the_admin_seed_as_a_prefixed_sibling() { ], "member item first, admin sibling second, one epoch" ); - assert!(a_adopt.lock().unwrap().is_empty(), "the fresh node adopts nothing"); + assert!( + a_adopt.lock().unwrap().is_empty(), + "the fresh node adopts nothing" + ); } // [int->REQ-MESH-4] the revoke lockout: a revoked node that KEPT its prior-epoch diff --git a/crates/spt-daemon/tests/resume_custody_aba.rs b/crates/spt-daemon/tests/resume_custody_aba.rs index 29bfee5f..7f3dd426 100644 --- a/crates/spt-daemon/tests/resume_custody_aba.rs +++ b/crates/spt-daemon/tests/resume_custody_aba.rs @@ -92,7 +92,8 @@ fn spawn_impostor() -> Impostor { fn seed_online_sessionless_endpoint(id: &str) -> std::path::PathBuf { let perch = resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&perch).unwrap(); - let mut rec = spt_store::info::InfoJson::new(id, "0", std::process::id(), "sid-prev", "live_agent"); + let mut rec = + spt_store::info::InfoJson::new(id, "0", std::process::id(), "sid-prev", "live_agent"); rec.adapter = Some("mockresume".to_string()); rec.controllable = Some(true); spt_store::info::write_info(&perch, &rec).unwrap(); @@ -201,7 +202,10 @@ fn matched_custody_pair_still_defers_the_reconcile() { must DEFER, never normalize the seat out from under it. got offlined={offlined:?}" ); assert_eq!( - spt_store::info::read_info(&perch).unwrap().status.as_deref(), + spt_store::info::read_info(&perch) + .unwrap() + .status + .as_deref(), Some("online"), "the deferred row keeps its online record for the incoming bind" ); diff --git a/crates/spt-daemon/tests/rosterprop.rs b/crates/spt-daemon/tests/rosterprop.rs index b9d1ab69..9761def4 100644 --- a/crates/spt-daemon/tests/rosterprop.rs +++ b/crates/spt-daemon/tests/rosterprop.rs @@ -49,25 +49,35 @@ fn test_exchange(store: Arc>, self_hex: String) -> RosterExch let sink_store = Arc::clone(&store); let status_store = Arc::clone(&store); RosterExchange { - provider: Arc::new(move |proven: &HashSet, self_addr: &serde_json::Value| { - let mut s = prov_store.lock().unwrap(); - let addr = if self_addr.is_null() { - None - } else { - Some(self_addr.clone()) - }; - for subnet in proven { - s.upsert_self(subnet, &self_hex, "lbl", "mid", addr.clone(), "1700000000", 5); - } - let mut entries = Vec::new(); - let mut tombs = Vec::new(); - for subnet in proven { - let (m, t) = s.roster_for(subnet); - entries.extend(m); - tombs.extend(t); - } - (entries, tombs) - }), + provider: Arc::new( + move |proven: &HashSet, self_addr: &serde_json::Value| { + let mut s = prov_store.lock().unwrap(); + let addr = if self_addr.is_null() { + None + } else { + Some(self_addr.clone()) + }; + for subnet in proven { + s.upsert_self( + subnet, + &self_hex, + "lbl", + "mid", + addr.clone(), + "1700000000", + 5, + ); + } + let mut entries = Vec::new(); + let mut tombs = Vec::new(); + for subnet in proven { + let (m, t) = s.roster_for(subnet); + entries.extend(m); + tombs.extend(t); + } + (entries, tombs) + }, + ), sink: Arc::new(move |entries, tombs| { let mut s = sink_store.lock().unwrap(); for e in &entries { diff --git a/crates/spt-daemon/tests/servicehost_supervision_e2e.rs b/crates/spt-daemon/tests/servicehost_supervision_e2e.rs index 9840774e..f9c04376 100644 --- a/crates/spt-daemon/tests/servicehost_supervision_e2e.rs +++ b/crates/spt-daemon/tests/servicehost_supervision_e2e.rs @@ -29,8 +29,8 @@ use std::sync::Mutex; use std::time::{Duration, Instant}; use spt_daemon::servicehost::{ - quiesce_for_update, reconcile_registered, release_hold_and_reconcile, status_registered, - Latch, Opportunity, QuiesceOutcome, ServiceOutcome, ServiceParams, ServiceSet, + quiesce_for_update, reconcile_registered, release_hold_and_reconcile, status_registered, Latch, + Opportunity, QuiesceOutcome, ServiceOutcome, ServiceParams, ServiceSet, }; use spt_runtime::manifest::{Service, ServiceStart}; @@ -223,7 +223,8 @@ fn the_published_stop_marker_earns_a_cooperative_exit_inside_grace() { ); assert!(gone, "the cooperative exit must leave no process behind"); assert!( - !dir.join(spt_daemon::servicehost::SERVICE_STOP_MARKER).exists(), + !dir.join(spt_daemon::servicehost::SERVICE_STOP_MARKER) + .exists(), "the marker is retired with the ceremony — a marker left behind would \ stop the service again the moment it came back" ); @@ -382,7 +383,8 @@ fn repeated_instant_exits_report_a_startup_fault_carrying_the_services_own_words keep suppressing it" ); assert!( - row.detail.is_some_and(|d| d.contains("MOCK_STARTUP_DIAGNOSTIC")), + row.detail + .is_some_and(|d| d.contains("MOCK_STARTUP_DIAGNOSTIC")), "and the operator-facing outcome carries the same evidence, not just \ the fault's name" ); diff --git a/crates/spt-daemon/tests/two_origin_spanning.rs b/crates/spt-daemon/tests/two_origin_spanning.rs index 02775179..1dbdb604 100644 --- a/crates/spt-daemon/tests/two_origin_spanning.rs +++ b/crates/spt-daemon/tests/two_origin_spanning.rs @@ -129,8 +129,14 @@ fn one_source_two_consumers_spans_and_merges() { }; let mut keys = BTreeMap::new(); keys.insert("session_id".to_string(), "A".to_string()); - let echo = fetch_history(&history, &keys, "cc", ParentHint::Infer, Duration::from_secs(10)) - .expect("history fetch"); + let echo = fetch_history( + &history, + &keys, + "cc", + ParentHint::Infer, + Duration::from_secs(10), + ) + .expect("history fetch"); assert_eq!(echo.len(), 1); assert!( echo[0].raw.contains("FULL-FIDELITY-A"), @@ -140,7 +146,11 @@ fn one_source_two_consumers_spans_and_merges() { // ── Consumer 2: the digest reads [digest] CONTRACT, spanned + merged ──────── let digest = project_endpoint_digest("cc", &DigestOverride::default()); - let inputs: Vec<_> = digest.turns.iter().filter_map(|t| t.input.as_deref()).collect(); + let inputs: Vec<_> = digest + .turns + .iter() + .filter_map(|t| t.input.as_deref()) + .collect(); assert_eq!( inputs, vec!["before clear", "after clear"], @@ -149,10 +159,13 @@ fn one_source_two_consumers_spans_and_merges() { // A /clear boundary divider separates the sessions (REQ-TERM-6). assert!( - digest.turns.iter().any(|t| t.entries.iter().any(|e| matches!( - e, - DigestEntry::Boundary { kind, .. } if kind == "clear" - ))), + digest + .turns + .iter() + .any(|t| t.entries.iter().any(|e| matches!( + e, + DigestEntry::Boundary { kind, .. } if kind == "clear" + ))), "a /clear boundary marker is present" ); @@ -184,7 +197,10 @@ fn one_source_two_consumers_spans_and_merges() { !rendered.contains("FULL-FIDELITY"), "the digest is contract-typed (extra adapter fields ignored): {rendered}" ); - assert!(rendered.contains("── /clear ──"), "boundary renders distinctively: {rendered}"); + assert!( + rendered.contains("── /clear ──"), + "boundary renders distinctively: {rendered}" + ); } // [int->REQ-DIGEST-GENERATION-SUPERSEDE] the flynn digest gen-union rig, end to @@ -265,9 +281,16 @@ fn digest_span_supersedes_a_replayed_generation() { // windowing: without supersede the span carries FIVE input turns // (a-one, a-two, [clear], a-one, a-two, b-tail) and all survive the window — // RED. With supersede the ancestor's two rows collapse into B's generation. - let over = DigestOverride { window_turns: Some(10), ..Default::default() }; + let over = DigestOverride { + window_turns: Some(10), + ..Default::default() + }; let digest = project_endpoint_digest("ccgen", &over); - let inputs: Vec<_> = digest.turns.iter().filter_map(|t| t.input.as_deref()).collect(); + let inputs: Vec<_> = digest + .turns + .iter() + .filter_map(|t| t.input.as_deref()) + .collect(); assert_eq!( inputs, vec!["a-one", "a-two", "b-tail"], @@ -276,13 +299,10 @@ fn digest_span_supersedes_a_replayed_generation() { // Gen A fully superseded (all rows replayed into B) → its /clear divider is // orphaned and trimmed (rule 5: a divider sits only between ≥1-row sessions). assert!( - !digest - .turns + !digest.turns.iter().any(|t| t + .entries .iter() - .any(|t| t.entries.iter().any(|e| matches!( - e, - DigestEntry::Boundary { .. } - ))), + .any(|e| matches!(e, DigestEntry::Boundary { .. }))), "no orphaned /clear divider once the replayed ancestor is emptied: {:?}", digest.turns ); diff --git a/crates/spt-daemon/tests/twohost.rs b/crates/spt-daemon/tests/twohost.rs index 1402644b..84be25c4 100644 --- a/crates/spt-daemon/tests/twohost.rs +++ b/crates/spt-daemon/tests/twohost.rs @@ -119,8 +119,8 @@ use sha2::{Digest, Sha256}; use spt_daemon::brain::Brain; use spt_daemon::broker::Broker; -use spt_daemon::effect::{Minter, MintedOp}; use spt_daemon::dispatch::{run_dispatch_loop, DispatchPaths}; +use spt_daemon::effect::{MintedOp, Minter}; use spt_daemon::nethost::{NetConfig, NetHost}; use spt_daemon::pump::{ run_peer_pump, PeerResolver, PumpCadence, PumpConfig, PumpHooks, PumpPaths, @@ -140,9 +140,9 @@ use spt_store::epoch::EpochSource; use spt_store::info::{self, InfoJson}; use spt_store::notif::{NotifRow, NotifStore}; use spt_store::perch::{self, ParentHint}; +use spt_store::roster::RosterStore; use spt_store::spool; use spt_store::subnet::SubnetStore; -use spt_store::roster::RosterStore; use spt_store::visibility::VisibilityStore; use tempfile::TempDir; @@ -479,14 +479,8 @@ fn canonical_pump_paths(scratch: PathBuf) -> PumpPaths { peer_addrs: home.join("identity").join("peer-addrs.json"), heartbeat: home.join("identity").join("pump-heartbeat.json"), rotations: home.join("identity").join("rotation-pending.json"), - seals: home - .join("identity") - .join("trust") - .join("seals.json"), - enrollments: home - .join("identity") - .join("trust") - .join("enrollments.json"), + seals: home.join("identity").join("trust").join("seals.json"), + enrollments: home.join("identity").join("trust").join("enrollments.json"), } } @@ -762,9 +756,13 @@ fn seed_offline_drive_shells() { Some(DRIVE_TGT_ALIAS), ) .expect("mint agent-owned offdrive"); - let g = - spt_store::shellinfo::spawn_record(&perch::owlery_dir(), GW_OWNER, "offdrive", Some(GW_ALIAS)) - .expect("mint gateway-owned offdrive"); + let g = spt_store::shellinfo::spawn_record( + &perch::owlery_dir(), + GW_OWNER, + "offdrive", + Some(GW_ALIAS), + ) + .expect("mint gateway-owned offdrive"); println!("TWOHOST role B: offline drive shells minted — {ID_B}/{a}, {GW_OWNER}/{g}"); } @@ -1063,14 +1061,17 @@ fn two_host_ladder_role_b() { rig.a_hex(), "and the node is B's OWN handshake-proven view of A, never A's claim" ); - println!("TWOHOST OK: knock landed at B from {} ({})", landed.knocker, landed.knocker_node); + println!( + "TWOHOST OK: knock landed at B from {} ({})", + landed.knocker, landed.knocker_node + ); // Approve it exactly as an agent would, through the guarded mutation seam, // and prove the resulting rule admits A on MSG. { use spt_store::access::{ - AccessRule, AccessRequest, AccessStore, Authority, MutationOp, MutationScope, - OriginQualifier, Provenance, RuleDecision, RuleMutation, Subject, surface, + surface, AccessRequest, AccessRule, AccessStore, Authority, MutationOp, MutationScope, + OriginQualifier, Provenance, RuleDecision, RuleMutation, Subject, }; let mut store = AccessStore::load_checked().expect("B access store readable"); store.set_endpoint_surface_mode(ID_B, surface::MSG, spt_store::access::Mode::Closed); @@ -1277,7 +1278,10 @@ fn two_host_ladder_role_b() { rig.wait, || { spool::peek_all_at(&gw_perch) - .map(|rows| rows.iter().any(|(_, _, body, _)| body.contains("op=\"press\""))) + .map(|rows| { + rows.iter() + .any(|(_, _, body, _)| body.contains("op=\"press\"")) + }) .unwrap_or(false) }, ); @@ -1295,17 +1299,25 @@ fn two_host_ladder_role_b() { // ordinary wire rest op. The durable rest record is the same observable // rung 8 proved; what is NEW is the bare-id ROUTE that produced the wake // (A asserts the routing decision on its side). - rig_wait("A-3: A's setup suspend landed (B suspended)", rig.wait, || { - spt_daemon::resting::read_rest(&perch_b) - .map(|r| r.state == spt_daemon::resting::RestState::Suspended) - .unwrap_or(false) - }); + rig_wait( + "A-3: A's setup suspend landed (B suspended)", + rig.wait, + || { + spt_daemon::resting::read_rest(&perch_b) + .map(|r| r.state == spt_daemon::resting::RestState::Suspended) + .unwrap_or(false) + }, + ); // [int->REQ-REST-VERB-ROUTING] - rig_wait("A-3: A's bare-id ROUTED wake landed (B active)", rig.wait, || { - spt_daemon::resting::read_rest(&perch_b) - .map(|r| r.state == spt_daemon::resting::RestState::Active) - .unwrap_or(false) - }); + rig_wait( + "A-3: A's bare-id ROUTED wake landed (B active)", + rig.wait, + || { + spt_daemon::resting::read_rest(&perch_b) + .map(|r| r.state == spt_daemon::resting::RestState::Active) + .unwrap_or(false) + }, + ); info::set_last_active(&perch_b, now_ms()).expect("re-stamp B's recency post-A-3"); println!("TWOHOST OK: A-3 bare-id wake (serve side)"); @@ -1352,10 +1364,14 @@ fn two_host_ladder_role_b() { // The child's control attach stamps the perch on this broker's sessions-poll // converge (KH 7.29) — polling in the probe IS the production trigger (the // reconcile tick's query_live_session_endpoints). - rig_wait("B-2: the attacher child's control stamps landed", rig.wait, || { - let _ = host_brain.sessions(); - info::read_info(&perch_b2).is_some_and(|i| i.controlled && i.driven_by.is_some()) - }); + rig_wait( + "B-2: the attacher child's control stamps landed", + rig.wait, + || { + let _ = host_brain.sessions(); + info::read_info(&perch_b2).is_some_and(|i| i.controlled && i.driven_by.is_some()) + }, + ); // Signal A (store-state, the rung-7 replication pattern): stamps seen — // A kills the child on this row's arrival. store_b @@ -1379,10 +1395,14 @@ fn two_host_ladder_role_b() { // sink is reaped on a sessions poll and the stamps CLEAR — the exact field // outcome B-2 exists for (a stale ONLINE+CONTROLLED that never healed). // [int->REQ-CONTROLLER-LIVENESS-REAP] - rig_wait("B-2: the severed controller's stamps CLEAR (reap + converge)", rig.wait, || { - let _ = host_brain.sessions(); - info::read_info(&perch_b2).is_some_and(|i| !i.controlled && i.driven_by.is_none()) - }); + rig_wait( + "B-2: the severed controller's stamps CLEAR (reap + converge)", + rig.wait, + || { + let _ = host_brain.sessions(); + info::read_info(&perch_b2).is_some_and(|i| !i.controlled && i.driven_by.is_none()) + }, + ); println!("TWOHOST OK: B-2 dead-controller reap cleared the stamps"); // ── NAMEPLATE rung N1b (releases#163) — the ER/DISCOVER conjunction's @@ -1431,14 +1451,18 @@ fn two_host_ladder_role_b() { // written by rung 3b (the same owner, subject and surface — restating it // would be `Unchanged` and prove nothing new), and what this rung adds is // the RECEIPT on the real wire, which is the leg that carries the courtesy. - rig_wait("courtesy: A's plain knock reached B's inbox", rig.wait, || { - spt_store::knock::KnockStore::load_checked() - .map(|s| { - s.pending_for(ID_B, now_ms()) - .any(|k| k.id == KNOCK_ID_COURTESY) - }) - .unwrap_or(false) - }); + rig_wait( + "courtesy: A's plain knock reached B's inbox", + rig.wait, + || { + spt_store::knock::KnockStore::load_checked() + .map(|s| { + s.pending_for(ID_B, now_ms()) + .any(|k| k.id == KNOCK_ID_COURTESY) + }) + .unwrap_or(false) + }, + ); { // ITS OWN BOUNDED CARRIER, for the reason the digest rung states at // length: `request_answer` blocks on the far side's ack, and only a @@ -1505,9 +1529,7 @@ fn two_host_ladder_role_b() { }; match rows .iter() - .find(|r| { - r.to_id.as_deref() == Some(ID_B_MINT) && r.seen.contains(ID_B_MINT) - }) + .find(|r| r.to_id.as_deref() == Some(ID_B_MINT) && r.seen.contains(ID_B_MINT)) .cloned() { Some(r) => { @@ -1637,27 +1659,31 @@ fn two_host_ladder_role_b() { let seal_rec = { let expected_hash = spt_store::seal::content_hash_hex(SEAL_CONTENT.as_bytes()); let mut found = None; - rig_wait("seal: A's record replicated into B's store", rig.wait, || { - let store = spt_store::seal::SealStore::load(); - found = store - .records - .iter() - .find(|r| r.content_hash == expected_hash) - .cloned(); - found.is_some() - }); + rig_wait( + "seal: A's record replicated into B's store", + rig.wait, + || { + let store = spt_store::seal::SealStore::load(); + found = store + .records + .iter() + .find(|r| r.content_hash == expected_hash) + .cloned(); + found.is_some() + }, + ); let rec = found.expect("rig_wait only returns once it is set"); // Describe answers: the record's fields crossed intact, minter fully // qualified with A's endpoint under the rig subnet, node half a key // prefix (never a hostname — the W3 gate ruling), kind honestly named. assert!( - rec.minter - .starts_with(&format!("{}:{}@", rig.subnet, ID_A)), + rec.minter.starts_with(&format!("{}:{}@", rig.subnet, ID_A)), "the replicated minter names A's endpoint fully qualified: {}", rec.minter ); assert!( - rec.minter.ends_with(&spt_net::net::registry::key_prefix(&rig.a_hex())), + rec.minter + .ends_with(&spt_net::net::registry::key_prefix(&rig.a_hex())), "the minter's node half is A's key short hex: {}", rec.minter ); @@ -1694,20 +1720,33 @@ fn two_host_ladder_role_b() { { let a_node = spt_net::net::registry::key_prefix(&rig.a_hex()); let mut found = None; - rig_wait("enroll: A's record replicated into B's store", rig.wait, || { - let store = spt_store::enroll::EnrollStore::load(); - found = store.find(&a_node, &rig.subnet).cloned(); - found.is_some() - }); + rig_wait( + "enroll: A's record replicated into B's store", + rig.wait, + || { + let store = spt_store::enroll::EnrollStore::load(); + found = store.find(&a_node, &rig.subnet).cloned(); + found.is_some() + }, + ); let rec = found.expect("rig_wait only returns once it is set"); assert_eq!( rec.pubkey_hex, "ab12cd34ef56ab12cd34ef56ab12cd34", "the enrolled pubkey crossed intact" ); - assert_eq!(rec.backend_kind, "test", "test-seam enrollments name themselves"); - assert_eq!(rec.node, a_node, "the node half is A's key short hex, never a hostname"); + assert_eq!( + rec.backend_kind, "test", + "test-seam enrollments name themselves" + ); + assert_eq!( + rec.node, a_node, + "the node half is A's key short hex, never a hostname" + ); assert_eq!(rec.node.len(), 8, "roster short form: 8 hex chars"); - assert_eq!(rec.subnet, rig.subnet, "the record's own field is the scope"); + assert_eq!( + rec.subnet, rig.subnet, + "the record's own field is the scope" + ); // The strict pair is the key: the same node under another subnet name // answers nothing here (W2's verify refuses by name off this exact // lookup shape). @@ -1730,20 +1769,23 @@ fn two_host_ladder_role_b() { // [int->REQ-SEAL-ENVELOPE-ATTR] { let mut sealed_arrival = None; - rig_wait("seal: the sealed message reached ID_B's spool", rig.wait, || { - let rows = match spool::peek_all_at(&perch_b) { - Ok(rows) => rows, - Err(_) => return false, - }; - sealed_arrival = rows.iter().find_map(|(_, _, body, _)| { - let p = spt_proto::event::parse_event(body)?; - let token = p.attr(spt_proto::event::EVENT_ATTR_SEAL)?.to_string(); - Some((token, p.body.clone())) - }); - sealed_arrival.is_some() - }); - let (token, delivered_body) = - sealed_arrival.expect("rig_wait only returns once it is set"); + rig_wait( + "seal: the sealed message reached ID_B's spool", + rig.wait, + || { + let rows = match spool::peek_all_at(&perch_b) { + Ok(rows) => rows, + Err(_) => return false, + }; + sealed_arrival = rows.iter().find_map(|(_, _, body, _)| { + let p = spt_proto::event::parse_event(body)?; + let token = p.attr(spt_proto::event::EVENT_ATTR_SEAL)?.to_string(); + Some((token, p.body.clone())) + }); + sealed_arrival.is_some() + }, + ); + let (token, delivered_body) = sealed_arrival.expect("rig_wait only returns once it is set"); assert_eq!( token, seal_rec.token, "the delivered attr cites exactly the seal A minted" @@ -1969,7 +2011,10 @@ fn two_host_ladder_role_a() { // [int->REQ-NET-1] let mut a = connect_retry(&broker_name); let conn = a - .net_dial(rig.peer_broker_addr("a"), Some(MintedOp::new(Minter::Cli, op()))) + .net_dial( + rig.peer_broker_addr("a"), + Some(MintedOp::new(Minter::Cli, op())), + ) .expect("dial B"); let opened = a .net_open_stream(conn.conn_id, Some(MintedOp::new(Minter::Cli, op()))) @@ -2059,8 +2104,15 @@ fn two_host_ladder_role_a() { println!("TWOHOST OK: file fetch (sid {sid})"); // [int->REQ-INST-8] - let viewport = - spt_daemon::attach::request_attach(&mut a, conn.conn_id, sid, 0, MintedOp::new(Minter::Rc, op()), spt_net::net::attach::AttachIntent::Control).expect("attach"); + let viewport = spt_daemon::attach::request_attach( + &mut a, + conn.conn_id, + sid, + 0, + MintedOp::new(Minter::Rc, op()), + spt_net::net::attach::AttachIntent::Control, + ) + .expect("attach"); a.net_stream_subscribe(viewport, 0) .expect("subscribe viewport"); spt_daemon::attach::send_attach_input( @@ -2433,9 +2485,10 @@ fn two_host_ladder_role_a() { "A-3 setup suspend applied an edge at B: {out:?}" ); rig_wait("A-3: B advertises Suspended at A", rig.wait, || { - registry.rows(&rig.subnet, ID_B).iter().any(|i| { - i.node == rig.b_hex() && i.status == spt_net::net::registry::Status::Suspended - }) + registry + .rows(&rig.subnet, ID_B) + .iter() + .any(|i| i.node == rig.b_hex() && i.status == spt_net::net::registry::Status::Suspended) }); // The PRODUCTION routing decision (red = the pre-fix local-only WOKE_FAIL). // [int->REQ-REST-VERB-ROUTING] @@ -2477,9 +2530,10 @@ fn two_host_ladder_role_a() { "A-3 routed wake applied an edge at B: {out:?}" ); rig_wait("A-3: B advertises Active again at A", rig.wait, || { - registry.rows(&rig.subnet, ID_B).iter().any(|i| { - i.node == rig.b_hex() && i.status == spt_net::net::registry::Status::Active - }) + registry + .rows(&rig.subnet, ID_B) + .iter() + .any(|i| i.node == rig.b_hex() && i.status == spt_net::net::registry::Status::Active) }); println!("TWOHOST OK: A-3 bare-id wake routed via the production assembly"); @@ -2552,18 +2606,16 @@ fn two_host_ladder_role_a() { rig_wait( "advert: B's LEGACY-shape endpoint reached A (blanket close ≠ DISCOVER close)", rig.wait, - || { - match registry - .rows(&rig.subnet, ID_B_LEGACY) - .into_iter() - .find(|i| i.node == rig.b_hex()) - { - Some(r) => { - legacy_row = Some(r); - true - } - None => false, + || match registry + .rows(&rig.subnet, ID_B_LEGACY) + .into_iter() + .find(|i| i.node == rig.b_hex()) + { + Some(r) => { + legacy_row = Some(r); + true } + None => false, }, ); let legacy_row = legacy_row.expect("rig_wait only returns once it is set"); @@ -2979,7 +3031,10 @@ fn two_host_ladder_role_a() { b.expect("digest-pull pump brain could not connect") }; let dig_conn = dig_a - .net_dial(rig.peer_broker_addr("a"), Some(MintedOp::new(Minter::Cli, op()))) + .net_dial( + rig.peer_broker_addr("a"), + Some(MintedOp::new(Minter::Cli, op())), + ) .expect("dial B for the digest pull"); // Poll until B's buffer answers — the rig's barrier discipline (observable @@ -3013,7 +3068,11 @@ fn two_host_ladder_role_a() { // B's CONTENT crossed — not an empty shell, and not A's own store. assert!(version >= 1, "the remote projection carries a version"); - assert_eq!(digest.turns.len(), 1, "B's one finished turn crossed: {digest:?}"); + assert_eq!( + digest.turns.len(), + 1, + "B's one finished turn crossed: {digest:?}" + ); let turn = &digest.turns[0]; assert_eq!( turn.input.as_deref(), @@ -3029,7 +3088,9 @@ fn two_host_ladder_role_a() { "REQ-DIGEST-SEAL-ON-IDLE: B's idle endpoint must send a SEALED trailing \ turn across the wire: {turn:?}" ); - let sealed_seq = turn.input_seq.expect("a sealed turn carries its stable seq"); + let sealed_seq = turn + .input_seq + .expect("a sealed turn carries its stable seq"); assert_eq!( sealed_seq, 0, "log-less sink: the sealed seq is the source line index B assigned" @@ -3039,7 +3100,11 @@ fn two_host_ladder_role_a() { | spt_term::DigestEntry::ToolSprint { seq, .. } => *seq, _ => None, }); - assert_eq!(entry_seq, Some(1), "B's agent reply sealed at its own line index"); + assert_eq!( + entry_seq, + Some(1), + "B's agent reply sealed at its own line index" + ); // SEQ STABILITY ACROSS A REAL WAN ROUND TRIP: pull again; an unchanged idle // endpoint must return the identical digest. This is the property that makes @@ -3069,7 +3134,6 @@ fn two_host_ladder_role_a() { ); } - // ── WAX-SEAL rung S2 (releases#21 W3) — THE SEALED CROSS-NODE SEND. The // body is the pre-composed sealed envelope — the SAME shape `spt send // --seal` authors at its one compose seam — carrying the token as the diff --git a/crates/spt-daemon/tests/wake_single_flight.rs b/crates/spt-daemon/tests/wake_single_flight.rs index 5f1c5744..08974ac4 100644 --- a/crates/spt-daemon/tests/wake_single_flight.rs +++ b/crates/spt-daemon/tests/wake_single_flight.rs @@ -47,7 +47,11 @@ use spt_daemon::Broker; static SEQ: AtomicU32 = AtomicU32::new(0); fn unique_name() -> String { let n = SEQ.fetch_add(1, Ordering::Relaxed); - format!("spt-daemon-wakesingleflight-{}-{}.sock", std::process::id(), n) + format!( + "spt-daemon-wakesingleflight-{}-{}.sock", + std::process::id(), + n + ) } fn kill_pid(pid: u32) { @@ -109,12 +113,17 @@ fn fire_wake(name: &str, endpoint: &str, barrier: Arc) -> u64 { let mut c = connect(name); let req = sleeper_spawn_req(endpoint); barrier.wait(); // both wakes cross this line together → concurrent dispatch_spawn - write_frame(&mut c, &Envelope::new(KIND_SPAWN, serde_json::to_value(req).unwrap())) - .expect("send spawn"); + write_frame( + &mut c, + &Envelope::new(KIND_SPAWN, serde_json::to_value(req).unwrap()), + ) + .expect("send spawn"); let sid = loop { match read_frame(&mut c) { Ok(f) if f.kind == KIND_SPAWNED => { - break serde_json::from_value::(f.payload).unwrap().session_id + break serde_json::from_value::(f.payload) + .unwrap() + .session_id } Ok(_) => continue, Err(e) => panic!("wake read failed: {e}"), @@ -157,7 +166,9 @@ fn two_concurrent_wakes_for_one_endpoint_spawn_exactly_one_launch_tree() { } } - eprintln!("=== W4 SINGLE-FLIGHT WAKE: sid1={sid1} sid2={sid2} session_count={session_count} ==="); + eprintln!( + "=== W4 SINGLE-FLIGHT WAKE: sid1={sid1} sid2={sid2} session_count={session_count} ===" + ); // Exactly one launch tree: both wakes resolved to the SAME session (the second // deduped to the first), and the broker holds exactly one session. @@ -172,7 +183,6 @@ fn two_concurrent_wakes_for_one_endpoint_spawn_exactly_one_launch_tree() { ); } - /// Fire one wake WITHOUT a barrier, returning the session id and how long the call took. /// The elapsed is the assertion subject in the stretch cell: a loser that stands down for /// the winner's whole slow spawn must NOT return early with a session of its own. @@ -180,12 +190,17 @@ fn fire_wake_timed(name: &str, endpoint: &str) -> (u64, Duration) { let t0 = std::time::Instant::now(); let mut c = connect(name); let req = sleeper_spawn_req(endpoint); - write_frame(&mut c, &Envelope::new(KIND_SPAWN, serde_json::to_value(req).unwrap())) - .expect("send spawn"); + write_frame( + &mut c, + &Envelope::new(KIND_SPAWN, serde_json::to_value(req).unwrap()), + ) + .expect("send spawn"); let sid = loop { match read_frame(&mut c) { Ok(f) if f.kind == KIND_SPAWNED => { - break serde_json::from_value::(f.payload).unwrap().session_id + break serde_json::from_value::(f.payload) + .unwrap() + .session_id } Ok(_) => continue, Err(e) => panic!("wake read failed: {e}"), diff --git a/crates/spt-daemon/tests/xfer.rs b/crates/spt-daemon/tests/xfer.rs index d20f2a2e..a5b0600f 100644 --- a/crates/spt-daemon/tests/xfer.rs +++ b/crates/spt-daemon/tests/xfer.rs @@ -22,7 +22,7 @@ use std::thread; use std::time::Duration; use spt_daemon::brain::{Brain, BrokerEvent}; -use spt_daemon::effect::{Minter, MintedOp}; +use spt_daemon::effect::{MintedOp, Minter}; use spt_daemon::nethost::{NetConfig, NetHost}; use spt_daemon::xfer::{fetch_file, push_file, serve_xfer, XferServeOutcome}; use spt_daemon::Broker; @@ -120,7 +120,9 @@ fn fetch_lands_byte_identical_with_progress_both_ends() { .expect("b status") .node_id_hex .expect("node id"); - let conn = operator.net_dial(a_addr, Some(MintedOp::new(Minter::Cli, 1))).expect("dial"); + let conn = operator + .net_dial(a_addr, Some(MintedOp::new(Minter::Cli, 1))) + .expect("dial"); let dest = dir.path().join("fetched").join("plan.md"); let dest_clone = dest.clone(); let progress_b_clone = progress_b.clone(); @@ -186,7 +188,10 @@ fn fetch_lands_byte_identical_with_progress_both_ends() { // Confinement: a traversal fetch is refused with an Err record (the // operator's fetch errors; nothing outside the root is served). let conn2 = operator - .net_dial(target.net_status().expect("a").addr, Some(MintedOp::new(Minter::Cli, 3))) + .net_dial( + target.net_status().expect("a").addr, + Some(MintedOp::new(Minter::Cli, 3)), + ) .expect("dial2"); let dest2 = dir.path().join("stolen.txt"); let fetcher2 = thread::spawn(move || { @@ -252,7 +257,9 @@ fn push_survives_target_brain_restart_exactly_once() { // Operator B: push on its own thread; it blocks until the commit echo — // which only the successor brain will send. let mut operator = connect_retry(&name_b); - let conn = operator.net_dial(a_addr, Some(MintedOp::new(Minter::Cli, 1))).expect("dial"); + let conn = operator + .net_dial(a_addr, Some(MintedOp::new(Minter::Cli, 1))) + .expect("dial"); let total = bytes.len() as u64; let pusher = thread::spawn(move || { push_file( diff --git a/crates/spt-live/src/digest.rs b/crates/spt-live/src/digest.rs index adbe4459..fcd5858c 100644 --- a/crates/spt-live/src/digest.rs +++ b/crates/spt-live/src/digest.rs @@ -68,7 +68,10 @@ impl std::error::Error for DigestExtractError {} /// The `[digest]` `source` template, or `[history]`'s `locate_template` as the /// DRY default. `None` when neither is declared. -pub fn resolve_source_template<'a>(digest: &'a Digest, history: Option<&'a History>) -> Option<&'a str> { +pub fn resolve_source_template<'a>( + digest: &'a Digest, + history: Option<&'a History>, +) -> Option<&'a str> { digest .source .as_deref() @@ -222,8 +225,14 @@ mod tests { resolve_source_template(&d, Some(&history)), Some(history.locate_template.as_deref().unwrap()) ); - let lines = extract_digest(&d, Some(&history), &no_keys(), Duration::from_secs(10), None) - .expect("extract"); + let lines = extract_digest( + &d, + Some(&history), + &no_keys(), + Duration::from_secs(10), + None, + ) + .expect("extract"); assert_eq!(lines.len(), 1); } @@ -312,6 +321,9 @@ mod tests { matches!(e, DigestExtractError::Runtime(RuntimeError::Timeout { .. })), "got {e}" ); - assert!(start.elapsed() < Duration::from_secs(5), "must return promptly"); + assert!( + start.elapsed() < Duration::from_secs(5), + "must return promptly" + ); } } diff --git a/crates/spt-live/src/echo.rs b/crates/spt-live/src/echo.rs index 947dd61f..f7742a0b 100644 --- a/crates/spt-live/src/echo.rs +++ b/crates/spt-live/src/echo.rs @@ -327,7 +327,10 @@ mod tests { Err(Error::new(ErrorKind::PermissionDenied, "os error 5")) }); assert_eq!(out.unwrap_err().kind(), ErrorKind::PermissionDenied); - assert_eq!(calls, ACCESS_DENIED_ATTEMPTS, "bounded: budget attempts, then loud"); + assert_eq!( + calls, ACCESS_DENIED_ATTEMPTS, + "bounded: budget attempts, then loud" + ); // A non-denied kind never retries. let mut calls = 0; diff --git a/crates/spt-live/src/ingest.rs b/crates/spt-live/src/ingest.rs index 7ec24a91..5aaf9489 100644 --- a/crates/spt-live/src/ingest.rs +++ b/crates/spt-live/src/ingest.rs @@ -431,8 +431,14 @@ project half let ingested = ingest_drops(drops.path(), "doyle", "proj-x", 1000, 60_000).expect("ingest"); assert_eq!(ingested.len(), 1); - assert!(!ingested[0].preserved, "a resolvable ingest CONSUMES the drop"); - assert!(!drop.exists(), "…and the file is gone, which is why the content rides"); + assert!( + !ingested[0].preserved, + "a resolvable ingest CONSUMES the drop" + ); + assert!( + !drop.exists(), + "…and the file is gone, which is why the content rides" + ); assert_eq!( ingested[0].content, body, "the funnel observes the file's bytes, markers and all" @@ -469,7 +475,10 @@ un-committable now ingested[0].preserved, "an un-committable project slice is kept, not consumed" ); - assert!(drop.exists(), "the drop is still on disk, awaiting a resolvable ingest"); + assert!( + drop.exists(), + "the drop is still on disk, awaiting a resolvable ingest" + ); }); } @@ -528,7 +537,10 @@ un-committable now ) .expect("route"); let live = read_live("doyle"); - assert!(!live.contains("!!checkpoint!!"), "sentinel stripped from durable live tier"); + assert!( + !live.contains("!!checkpoint!!"), + "sentinel stripped from durable live tier" + ); assert!(live.contains("do the thing"), "inter-marker text kept"); assert!(live.contains("brief")); }); @@ -567,7 +579,10 @@ un-committable now "doyle", )) .unwrap(); - assert_eq!(role, "ORIGINAL ROLE", "no automated writer touches live-role.md"); + assert_eq!( + role, "ORIGINAL ROLE", + "no automated writer touches live-role.md" + ); assert!(read_live("doyle").contains("the brief")); }); } @@ -620,10 +635,17 @@ un-committable now ) .expect("route"); let tiers: Vec = writes.iter().map(|w| w.tier).collect(); - assert_eq!(tiers, vec![Tier::Live], "live commits; project tier skipped on empty id"); + assert_eq!( + tiers, + vec![Tier::Live], + "live commits; project tier skipped on empty id" + ); let cs = ContextStore::open_or_init().unwrap(); - assert!(cs.branch_store().tip("a-doyle").unwrap().is_some(), "a- committed"); + assert!( + cs.branch_store().tip("a-doyle").unwrap().is_some(), + "a- committed" + ); assert!( cs.branch_store().tip("p-").unwrap().is_none(), "no p- branch minted for an owlery-internal / unresolved anchor" @@ -756,15 +778,17 @@ what I do here ) .unwrap(); - let ingested = - ingest_drops(drops.path(), "doyle", "", 1000, 60_000).expect("ingest"); + let ingested = ingest_drops(drops.path(), "doyle", "", 1000, 60_000).expect("ingest"); assert_eq!(ingested.len(), 1); // Live tier committed this pass (the slice that CAN be written). assert!(read_live("doyle").contains("who I am")); let tiers: Vec = ingested[0].writes.iter().map(|w| w.tier).collect(); assert_eq!(tiers, vec![Tier::Live], "only the live tier is written"); - assert!(ingested[0].preserved, "un-committable project slice ⇒ preserved"); + assert!( + ingested[0].preserved, + "un-committable project slice ⇒ preserved" + ); // The drop was NOT deleted — it survives for a later resolvable ingest. assert!(drop.exists(), "preserved drop must remain on disk"); @@ -831,11 +855,17 @@ what I do here assert!( matches!( third[0].writes.as_slice(), - [TierWrite { tier: Tier::Project, outcome: WriteOutcome::Written { .. } }] + [TierWrite { + tier: Tier::Project, + outcome: WriteOutcome::Written { .. } + }] ), "the project slice finally lands" ); - assert!(!drop.exists(), "drop deleted once its project slice is durable"); + assert!( + !drop.exists(), + "drop deleted once its project slice is durable" + ); assert!(read_project("proj-x", "doyle").contains("what I do here")); // Nothing lost: both texts durably present across the cycle. assert!(read_live("doyle").contains("who I am")); @@ -856,7 +886,10 @@ what I do here let untagged = drops.path().join("doyle-commune.md"); std::fs::write(&untagged, "just an operator note, no tags").unwrap(); let ing = ingest_drops(drops.path(), "doyle", "", 1000, 60_000).expect("ingest"); - assert!(!ing[0].preserved, "untagged fallback is not a project slice"); + assert!( + !ing[0].preserved, + "untagged fallback is not a project slice" + ); assert!(!untagged.exists(), "untagged drop consumed"); assert!(read_live("doyle").contains("just an operator note")); @@ -894,13 +927,15 @@ what I do here ) .unwrap(); - let ingested = - ingest_drops(drops.path(), "doyle", "", 1000, 60_000).expect("ingest"); + let ingested = ingest_drops(drops.path(), "doyle", "", 1000, 60_000).expect("ingest"); assert!( !ingested[0].preserved, "marker-only project slice carries no content ⇒ not deferred" ); - assert!(!drop.exists(), "contentless-project drop is deleted, not stranded"); + assert!( + !drop.exists(), + "contentless-project drop is deleted, not stranded" + ); assert!(read_live("doyle").contains("real live text")); }); } @@ -926,11 +961,13 @@ what I do here .unwrap(); // Ingest under an EMPTY project_id: live commits, project defers. - let ingested = - ingest_drops(drops.path(), "doyle", "", 1000, 60_000).expect("ingest"); + let ingested = ingest_drops(drops.path(), "doyle", "", 1000, 60_000).expect("ingest"); assert_eq!(ingested.len(), 1); assert_eq!(ingested[0].kind, DropKind::Signoff); - assert!(ingested[0].preserved, "un-committable project slice ⇒ preserved"); + assert!( + ingested[0].preserved, + "un-committable project slice ⇒ preserved" + ); // Live slice committed this pass. assert!(read_live("doyle").contains("signing off now")); @@ -939,8 +976,14 @@ what I do here // The signoff sentinel is GONE — it must never linger (the sweep // rationale); the pending was carried to the COMMUNE suffix instead. - assert!(!signoff.exists(), "signoff sentinel deleted, never left to be swept"); - assert!(commune.exists(), "deferred pending carried under the commune suffix"); + assert!( + !signoff.exists(), + "signoff sentinel deleted, never left to be swept" + ); + assert!( + commune.exists(), + "deferred pending carried under the commune suffix" + ); // The commune-suffix pending is the project-only form. let pending = std::fs::read_to_string(&commune).unwrap(); @@ -954,10 +997,15 @@ what I do here // Simulate the listener-start sweep: nothing to reap (no signoff file), // and the commune pending must survive it intact. - let swept = crate::signoff::sweep_stale_signoff(drops.path(), "doyle") - .expect("sweep"); - assert!(!swept, "no stale signoff to reap — the pending is not signoff-named"); - assert!(commune.exists(), "sweep must not touch the commune-suffix pending"); + let swept = crate::signoff::sweep_stale_signoff(drops.path(), "doyle").expect("sweep"); + assert!( + !swept, + "no stale signoff to reap — the pending is not signoff-named" + ); + assert!( + commune.exists(), + "sweep must not touch the commune-suffix pending" + ); assert_eq!( std::fs::read_to_string(&commune).unwrap(), pending, @@ -968,15 +1016,24 @@ what I do here let resolved = ingest_drops(drops.path(), "doyle", "proj-x", 2000, 60_000).expect("ingest"); assert_eq!(resolved.len(), 1); - assert!(!resolved[0].preserved, "resolved ingest consumes the pending"); + assert!( + !resolved[0].preserved, + "resolved ingest consumes the pending" + ); assert!( matches!( resolved[0].writes.as_slice(), - [TierWrite { tier: Tier::Project, outcome: WriteOutcome::Written { .. } }] + [TierWrite { + tier: Tier::Project, + outcome: WriteOutcome::Written { .. } + }] ), "the project slice finally lands" ); - assert!(!commune.exists(), "pending deleted once its project slice is durable"); + assert!( + !commune.exists(), + "pending deleted once its project slice is durable" + ); assert!(read_project("proj-x", "doyle").contains("the project brief")); }); } @@ -1005,8 +1062,7 @@ what I do here ) .unwrap(); - let ingested = - ingest_drops(drops.path(), "doyle", "", 1000, 60_000).expect("ingest"); + let ingested = ingest_drops(drops.path(), "doyle", "", 1000, 60_000).expect("ingest"); assert_eq!(ingested.len(), 2, "both drops processed in one pass"); assert!( ingested.iter().all(|i| i.preserved), diff --git a/crates/spt-live/src/inject.rs b/crates/spt-live/src/inject.rs index 8b3d1c32..fa6e3228 100644 --- a/crates/spt-live/src/inject.rs +++ b/crates/spt-live/src/inject.rs @@ -78,12 +78,18 @@ mod tests { record_context_injection("doyle", KIND_OWL_MESSAGE, "from todlando: hi there"); let log = std::fs::read_to_string(perch.join("digest.log")).unwrap(); let line = log.lines().next().unwrap(); - assert!(line.contains(r#""context_kind":"owl_message""#), "discriminator: {line}"); + assert!( + line.contains(r#""context_kind":"owl_message""#), + "discriminator: {line}" + ); assert!( line.contains(r#""body":"from todlando: hi there""#), "whitespace-normalized body: {line}" ); - assert!(line.contains(r#""ts":"#) && line.contains("Z\"}"), "rfc3339-utc ts: {line}"); + assert!( + line.contains(r#""ts":"#) && line.contains("Z\"}"), + "rfc3339-utc ts: {line}" + ); }); } diff --git a/crates/spt-live/src/lib.rs b/crates/spt-live/src/lib.rs index 5580988d..5bcdb0b2 100644 --- a/crates/spt-live/src/lib.rs +++ b/crates/spt-live/src/lib.rs @@ -28,8 +28,8 @@ pub mod context; pub mod digest; pub mod echo; pub mod history; -pub mod inject; pub mod ingest; +pub mod inject; pub mod outbound; pub mod psyche; pub mod pulse; @@ -45,13 +45,13 @@ pub use context::{write_context, write_context_joined, WriteOutcome, WriteSource pub use digest::{extract_digest, resolve_source_template, DigestExtractError}; pub use echo::{run_echo_commune, stamp_provenance, EchoError, EchoResult}; pub use history::{fetch_history, HistoryError, HistoryRecord}; -pub use inject::{ - record_context_injection, KIND_ECHO_COMMUNE, KIND_OWL_MESSAGE, KIND_PSYCHE_DOWNLOAD, -}; pub use ingest::{ ingest_drops, resolve_endpoint_drop_dir, route_slices, route_two_slice, DropAnchor, DropKind, Ingested, ResolvedDrop, Tier, TierWrite, }; +pub use inject::{ + record_context_injection, KIND_ECHO_COMMUNE, KIND_OWL_MESSAGE, KIND_PSYCHE_DOWNLOAD, +}; pub use outbound::{parse_psyche_intents, PsycheIntent}; pub use psyche::{PsycheError, PsycheHandle}; pub use pulse::{tick, PulseConfig, TickOutcome}; diff --git a/crates/spt-live/src/pulse.rs b/crates/spt-live/src/pulse.rs index c5f7a699..50d9e51a 100644 --- a/crates/spt-live/src/pulse.rs +++ b/crates/spt-live/src/pulse.rs @@ -22,7 +22,9 @@ use crate::context::DEFAULT_PROTECTION_WINDOW_MS; use crate::ingest::{ingest_drops, Ingested}; -use spt_store::perch::{resolve_edge_echo_file, resolve_idle_file, resolve_turn_echo_file, ParentHint}; +use spt_store::perch::{ + resolve_edge_echo_file, resolve_idle_file, resolve_turn_echo_file, ParentHint, +}; use std::path::Path; use std::time::{Duration, SystemTime}; @@ -402,7 +404,10 @@ mod tests { ) .expect("tick"); assert_eq!(t1.ingested.len(), 1); - assert!(t1.ingested[0].preserved, "unresolved project slice is preserved"); + assert!( + t1.ingested[0].preserved, + "unresolved project slice is preserved" + ); assert!(drop.exists(), "preserved drop remains for a later pulse"); let live_path = live_context_file(&tracked_dir(), "perri"); @@ -424,8 +429,14 @@ mod tests { ) .expect("tick"); assert_eq!(t2.ingested.len(), 1); - assert!(!t2.ingested[0].preserved, "resolved pulse consumes the drop"); - assert!(!drop.exists(), "drop gone once the project slice is durable"); + assert!( + !t2.ingested[0].preserved, + "resolved pulse consumes the drop" + ); + assert!( + !drop.exists(), + "drop gone once the project slice is durable" + ); let project_path = project_context_file(&tracked_dir(), "perri-proj", "perri"); assert!( diff --git a/crates/spt-live/src/reconcile.rs b/crates/spt-live/src/reconcile.rs index 8e7b4a8a..4a6c4fa2 100644 --- a/crates/spt-live/src/reconcile.rs +++ b/crates/spt-live/src/reconcile.rs @@ -196,7 +196,9 @@ pub fn reconcile_file( None => return Ok(ReconcileOutcome::TurnFailed(TurnError::EmptyOutput)), }, Err(e) => { - spt_proto::emit_line_err!("RECONCILE_TURN_FAILED:{file_rel}: {e} (artifacts preserved)"); + spt_proto::emit_line_err!( + "RECONCILE_TURN_FAILED:{file_rel}: {e} (artifacts preserved)" + ); return Ok(ReconcileOutcome::TurnFailed(e)); } }; @@ -221,7 +223,9 @@ pub fn reconcile_file( &[], &format!("reconcile: {file_rel} (cleared {cleared})"), )?; - spt_proto::emit_line_err!("RECONCILE_MERGED:{file_rel} (cleared {cleared} artifact(s))"); + spt_proto::emit_line_err!( + "RECONCILE_MERGED:{file_rel} (cleared {cleared} artifact(s))" + ); Ok(ReconcileOutcome::Reconciled { cleared }) } WriteOutcome::Suppressed { .. } => { diff --git a/crates/spt-live/src/resume.rs b/crates/spt-live/src/resume.rs index 5ef8d170..408787fc 100644 --- a/crates/spt-live/src/resume.rs +++ b/crates/spt-live/src/resume.rs @@ -236,7 +236,9 @@ pub fn download_psyche_context( fn append_pending(out: &mut String, tag: &str, file: Option<&ResolvedDrop>) { let Some(drop) = file else { return }; let path = drop.path.as_path(); - let Ok(body) = std::fs::read_to_string(path) else { return }; + let Ok(body) = std::fs::read_to_string(path) else { + return; + }; // Strip the checkpoint sentinel before presenting (pre-synthesis strip point): // the marker is spt-core control metadata, never agent context. The inter-marker // text is kept. [impl->REQ-RESUME-CONTEXT-PULL] @@ -319,7 +321,8 @@ mod tests { assert_eq!(slices.project.as_deref(), Some("project mind")); // A different project sees the live tier only (no cross-project leak). - let other = download_psyche_context("doyle", "other-proj", None, None).expect("live only"); + let other = + download_psyche_context("doyle", "other-proj", None, None).expect("live only"); let slices = spt_proto::envelope::parse_two_slice(&other); assert_eq!(slices.live.as_deref(), Some("live mind")); assert_eq!(slices.project, None); @@ -393,7 +396,10 @@ mod tests { let live_at = got.find("").expect("live slice"); let proj_at = got.find("").expect("project slice"); assert!(role_at < live_at, "role renders before live-context"); - assert!(live_at < proj_at, "live-context renders before project-context"); + assert!( + live_at < proj_at, + "live-context renders before project-context" + ); // The inbound two-slice grammar ignores the injected role. let slices = spt_proto::envelope::parse_two_slice(&got); assert_eq!(slices.live.as_deref(), Some("live mind")); @@ -402,7 +408,8 @@ mod tests { // A role-only mind still renders (role first, nothing else). assert!(download_psyche_context("solo", "proj-x", None, None).is_none()); std::fs::write(cs.live_role_path("solo").unwrap(), "just a role").unwrap(); - let got = download_psyche_context("solo", "proj-x", None, None).expect("role-only composes"); + let got = + download_psyche_context("solo", "proj-x", None, None).expect("role-only composes"); assert!(got.contains("\njust a role\n")); assert!(!got.contains(""), "no live tier yet"); }); @@ -424,7 +431,10 @@ mod tests { // Absent drop → no pending slice. let got = download_psyche_context("doyle", "proj-x", Some(®istered(&commune)), None) .expect("composed"); - assert!(!got.contains(""), "absent drop adds nothing"); + assert!( + !got.contains(""), + "absent drop adds nothing" + ); // Present drop → appended AFTER the durable tiers, body verbatim. std::fs::write(&commune, "\nfresh brief\n").unwrap(); @@ -443,8 +453,9 @@ mod tests { ); // Pending-only (no durable for this id) still composes the pending slice. - let got = download_psyche_context("nobody", "proj-x", Some(®istered(&commune)), None) - .expect("pending-only composes"); + let got = + download_psyche_context("nobody", "proj-x", Some(®istered(&commune)), None) + .expect("pending-only composes"); assert!(got.contains("")); assert!(!got.contains("") && !got.contains("")); }); @@ -458,8 +469,11 @@ mod tests { with_home(|_| { let drops = tempfile::tempdir().unwrap(); let commune = drops.path().join("ckpt-commune.md"); - std::fs::write(&commune, "live brief !!checkpoint!! wake up and ship !!checkpoint!! tail") - .unwrap(); + std::fs::write( + &commune, + "live brief !!checkpoint!! wake up and ship !!checkpoint!! tail", + ) + .unwrap(); let got = download_psyche_context("ckpt", "proj-x", Some(®istered(&commune)), None) .expect("pending-only composes"); assert!(got.contains("")); @@ -467,7 +481,10 @@ mod tests { !got.contains("!!checkpoint!!"), "the sentinel must be stripped from presented context" ); - assert!(got.contains("wake up and ship"), "inter-marker wake text is kept"); + assert!( + got.contains("wake up and ship"), + "inter-marker wake text is kept" + ); assert!(got.contains("live brief")); }); } @@ -524,8 +541,8 @@ mod tests { with_home(|_| { let cs = spt_store::contextstore::ContextStore::open_or_init().unwrap(); std::fs::write(cs.live_context_path("todlando").unwrap(), "durable mind").unwrap(); - let brief = download_psyche_context("todlando", "proj-x", None, None) - .expect("composed"); + let brief = + download_psyche_context("todlando", "proj-x", None, None).expect("composed"); let clean = PsycheHostError { reason: "turn: harness exited 1".to_string(), ts: "2026-08-25T23:12:03Z".to_string(), @@ -535,8 +552,10 @@ mod tests { let notice = ingest_fault_notice("todlando", Some(&clean)); assert_eq!(notice, None); let composed = match notice { - Some(line) => format!("{line} -{brief}"), + Some(line) => format!( + "{line} +{brief}" + ), None => brief.clone(), }; assert_eq!( diff --git a/crates/spt-live/src/turn.rs b/crates/spt-live/src/turn.rs index 6a986eb2..012d04e1 100644 --- a/crates/spt-live/src/turn.rs +++ b/crates/spt-live/src/turn.rs @@ -120,7 +120,11 @@ fn stream_tail(s: &str) -> String { .chars() .map(|c| if c == '\n' || c == '\r' { ' ' } else { c }) .collect(); - if cut > 0 { format!("…{tail}") } else { tail } + if cut > 0 { + format!("…{tail}") + } else { + tail + } } /// Run one bounded live-Psyche turn: feed `stdin` to the `psyche_resume` role, diff --git a/crates/spt-msg/src/deliver.rs b/crates/spt-msg/src/deliver.rs index 386aadcc..c58d432e 100644 --- a/crates/spt-msg/src/deliver.rs +++ b/crates/spt-msg/src/deliver.rs @@ -285,7 +285,10 @@ mod tests { ); let cleaned = sender_supplied(&sealed); let p = spt_proto::event::parse_event(&cleaned).expect("still a typed envelope"); - assert_eq!(p.attr(spt_proto::event::EVENT_ATTR_SEAL), Some("bcdfgh2345")); + assert_eq!( + p.attr(spt_proto::event::EVENT_ATTR_SEAL), + Some("bcdfgh2345") + ); assert_eq!(p.attr(spt_proto::event::EVENT_ATTR_TRUST_WARNING), None); assert_eq!(p.body, "promote v0.60.0 to stable"); } diff --git a/crates/spt-msg/src/emit.rs b/crates/spt-msg/src/emit.rs index c9066096..bd92bb41 100644 --- a/crates/spt-msg/src/emit.rs +++ b/crates/spt-msg/src/emit.rs @@ -115,8 +115,7 @@ pub fn render_event_whole_warned_for( body: &str, warning: &str, ) -> (String, bool) { - let (line, typed) = - compose_line_warned_at(&tracked_dir(), owner, from, body, Some(warning)); + let (line, typed) = compose_line_warned_at(&tracked_dir(), owner, from, body, Some(warning)); (line, !typed) } @@ -331,7 +330,10 @@ mod tests { ); let p = parse_event(&whole).unwrap(); let json = p.attr("mnemonics-json").expect("attr present"); - assert!(json.starts_with('[') && json.ends_with(']'), "array: {json}"); + assert!( + json.starts_with('[') && json.ends_with(']'), + "array: {json}" + ); assert!(json.contains("my operator"), "carries the record: {json}"); assert_eq!(p.body, "hi", "the body is untouched by the attr"); } @@ -452,8 +454,7 @@ mod tests { let json = p.attr("mnemonics-json").expect("attr present"); assert_eq!( json, - spt_store::monic::matched_for_delivery(root.path(), "owner", "stranger", "hi") - .unwrap(), + spt_store::monic::matched_for_delivery(root.path(), "owner", "stranger", "hi").unwrap(), "the attr decodes back to exactly what the primitive produced" ); } @@ -581,4 +582,3 @@ mod tests { ); } } - diff --git a/crates/spt-msg/src/ready.rs b/crates/spt-msg/src/ready.rs index 17bbbeca..87ba3c53 100644 --- a/crates/spt-msg/src/ready.rs +++ b/crates/spt-msg/src/ready.rs @@ -159,10 +159,10 @@ impl ReadyAgent { ); let backlog: Vec<(String, String)> = spool::drain_non_deferred_audited_at(&perch_path, &audit) - .map_err(|e| format!("Failed to drain spool backlog: {}", e))? - .into_iter() - .map(|m| (m.from, m.body)) - .collect(); + .map_err(|e| format!("Failed to drain spool backlog: {}", e))? + .into_iter() + .map(|m| (m.from, m.body)) + .collect(); Ok(( ReadyAgent { @@ -304,8 +304,14 @@ mod tests { ); let perch_path = perch::resolve_perch_path(reserved, ParentHint::Infer); assert!(!perch_path.exists(), "no perch dir was created"); - assert!(info::read_info(&perch_path).is_none(), "no identity was minted"); - assert!(!deliver::perch_exists(reserved), "nothing became resolvable"); + assert!( + info::read_info(&perch_path).is_none(), + "no identity was minted" + ); + assert!( + !deliver::perch_exists(reserved), + "nothing became resolvable" + ); } // [unit->REQ-MSG-3] backlog spooled while offline drains on startup. diff --git a/crates/spt-msg/src/ring.rs b/crates/spt-msg/src/ring.rs index 5b4e16a2..1fc42f38 100644 --- a/crates/spt-msg/src/ring.rs +++ b/crates/spt-msg/src/ring.rs @@ -210,12 +210,8 @@ pub fn ring( // [impl->REQ-ER-INBOUND-LOCK-ALL-PATHS] // The SUBJECT is the proven sender, never `from` (releases#215). // [impl->REQ-ACL-LOCAL-SUBJECT-ONE-SHAPE] - if spt_store::gate::admit_local_delivery( - target, - spt_store::access::surface::MSG, - sender_proven, - ) - .is_deny() + if spt_store::gate::admit_local_delivery(target, spt_store::access::surface::MSG, sender_proven) + .is_deny() { return RingOutcome::Refused; } @@ -411,7 +407,14 @@ mod tests { } }); - let outcome = ring(&target, &from, None, "ping", Duration::from_secs(5), &owlery); + let outcome = ring( + &target, + &from, + None, + "ping", + Duration::from_secs(5), + &owlery, + ); h.join().unwrap(); match outcome { RingOutcome::Replied { from, body } => { @@ -457,7 +460,11 @@ mod tests { Duration::from_millis(200), &owlery, ); - assert_eq!(outcome, RingOutcome::TimedOut, "the ring itself is ordinary"); + assert_eq!( + outcome, + RingOutcome::TimedOut, + "the ring itself is ordinary" + ); let log = spt_store::access::RecentOutbound::load(); assert!( @@ -553,7 +560,10 @@ mod tests { RingOutcome::TimedOut, "the two silences must stay distinguishable at the outcome, not just in prose" ); - assert!(perch_gone(&from), "ephemeral perch leaked on the spooled path"); + assert!( + perch_gone(&from), + "ephemeral perch leaked on the spooled path" + ); assert_eq!(spool::pending_count_at(&perch_path).unwrap(), 1); } @@ -579,16 +589,29 @@ mod tests { deliver::deliver(&caller, &replier, "pong", &owlery2); }); - let outcome = ring(&target, &from, None, "ping", Duration::from_secs(10), &owlery); + let outcome = ring( + &target, + &from, + None, + "ping", + Duration::from_secs(10), + &owlery, + ); h.join().unwrap(); match outcome { - RingOutcome::Replied { from: replier, body } => { + RingOutcome::Replied { + from: replier, + body, + } => { assert_eq!(replier, target); assert!(body.contains("pong"), "got {body}"); } other => panic!("a late reply must still be returned, got {other:?}"), } - assert!(perch_gone(&from), "ephemeral perch leaked on the late-reply path"); + assert!( + perch_gone(&from), + "ephemeral perch leaked on the late-reply path" + ); } /// Build the shape a working live agent presents to a ring when its ready @@ -618,7 +641,14 @@ mod tests { let info_before = fs::read(perch::resolve_info_file(&from, ParentHint::Infer)).unwrap(); let spool_before = fs::read(perch::resolve_spool_db(&from, ParentHint::Infer)).unwrap(); - let outcome = ring(&target, &from, None, "anyone?", Duration::from_millis(200), &owlery); + let outcome = ring( + &target, + &from, + None, + "anyone?", + Duration::from_millis(200), + &owlery, + ); assert_eq!( outcome, @@ -628,7 +658,10 @@ mod tests { }, "an existing perch must be refused, not adopted" ); - assert!(perch_path.exists(), "ring deleted a perch it did not create"); + assert!( + perch_path.exists(), + "ring deleted a perch it did not create" + ); assert_eq!( fs::read(perch::resolve_info_file(&from, ParentHint::Infer)).unwrap(), info_before, @@ -660,8 +693,8 @@ mod tests { let victim = unique_id("test-ring-disclose-victim"); let (_agent, _) = ReadyAgent::start(&target).unwrap(); // online, silent - // The victim: a live-shaped perch (marker down) holding mail from a - // THIRD id — not from the ringer, and not for the ringer. + // The victim: a live-shaped perch (marker down) holding mail from a + // THIRD id — not from the ringer, and not for the ringer. let perch_path = perch::resolve_perch_path(&victim, ParentHint::Infer); fs::create_dir_all(&perch_path).unwrap(); let rec = InfoJson::new(&victim, "earlier", std::process::id(), "sess", "live_agent"); @@ -671,7 +704,14 @@ mod tests { // A SECOND id rings, presenting itself as the victim's from-id — the // adoption path's entry condition. - let outcome = ring(&target, &victim, None, "you up?", Duration::from_millis(200), &owlery); + let outcome = ring( + &target, + &victim, + None, + "you up?", + Duration::from_millis(200), + &owlery, + ); match &outcome { RingOutcome::Replied { from, body } => panic!( @@ -711,7 +751,14 @@ mod tests { let info_file = perch::resolve_info_file(&from, ParentHint::Infer); fs::write(&info_file, b"{\"id\": \"trunca").unwrap(); - let outcome = ring(&target, &from, None, "hello?", Duration::from_millis(200), &owlery); + let outcome = ring( + &target, + &from, + None, + "hello?", + Duration::from_millis(200), + &owlery, + ); assert_eq!( outcome, @@ -741,7 +788,14 @@ mod tests { let spool_file = perch::resolve_spool_db(&from, ParentHint::Infer); let spool_before = fs::read(&spool_file).unwrap(); - let outcome = ring(&target, &from, None, "hello?", Duration::from_millis(200), &owlery); + let outcome = ring( + &target, + &from, + None, + "hello?", + Duration::from_millis(200), + &owlery, + ); assert_eq!( outcome, @@ -768,7 +822,14 @@ mod tests { let perch_path = perch::resolve_perch_path(&from, ParentHint::Infer); fs::create_dir_all(&perch_path).unwrap(); - let outcome = ring(&target, &from, None, "hello?", Duration::from_millis(200), &owlery); + let outcome = ring( + &target, + &from, + None, + "hello?", + Duration::from_millis(200), + &owlery, + ); assert_eq!( outcome, diff --git a/crates/spt-msg/src/wire.rs b/crates/spt-msg/src/wire.rs index 1ce27d92..723377fd 100644 --- a/crates/spt-msg/src/wire.rs +++ b/crates/spt-msg/src/wire.rs @@ -100,14 +100,20 @@ mod tests { #[test] fn encode_decode_round_trips_structural() { let payload = encode_frame("alice", "hi\nbob"); - assert_eq!(decode_frame(&payload).unwrap(), ("alice".to_string(), "hi\nbob".to_string())); + assert_eq!( + decode_frame(&payload).unwrap(), + ("alice".to_string(), "hi\nbob".to_string()) + ); } // [unit->REQ-MSG-ENVELOPE] empty from => anonymous (len-0 from prefix), body intact. #[test] fn encode_empty_from_is_anonymous() { let payload = encode_frame("", "no reply"); - assert_eq!(decode_frame(&payload).unwrap(), ("".to_string(), "no reply".to_string())); + assert_eq!( + decode_frame(&payload).unwrap(), + ("".to_string(), "no reply".to_string()) + ); } // [unit->REQ-MSG-ENVELOPE] a typed body rides the wire verbatim — the diff --git a/crates/spt-net/src/net.rs b/crates/spt-net/src/net.rs index 7c92cf51..e378548b 100644 --- a/crates/spt-net/src/net.rs +++ b/crates/spt-net/src/net.rs @@ -7,10 +7,10 @@ pub mod answermsg; pub mod attach; +pub mod codeseal; pub mod digestpull; pub mod endpoint; pub mod forkmsg; -pub mod codeseal; pub mod knockmsg; pub mod mesh; pub mod ndjson; diff --git a/crates/spt-net/src/net/answermsg.rs b/crates/spt-net/src/net/answermsg.rs index 493cd01c..5d39da5c 100644 --- a/crates/spt-net/src/net/answermsg.rs +++ b/crates/spt-net/src/net/answermsg.rs @@ -208,8 +208,14 @@ mod tests { // redemption family's third outcome exists to prevent. #[test] fn the_receipt_has_two_answers_and_no_word_for_silence() { - assert_eq!(AnswerRecord::new("k-1", "ling", true).outcome, token::APPROVED); - assert_eq!(AnswerRecord::new("k-1", "ling", false).outcome, token::DENIED); + assert_eq!( + AnswerRecord::new("k-1", "ling", true).outcome, + token::APPROVED + ); + assert_eq!( + AnswerRecord::new("k-1", "ling", false).outcome, + token::DENIED + ); assert_ne!(token::APPROVED, token::DENIED); for t in [token::APPROVED, token::DENIED] { assert!( diff --git a/crates/spt-net/src/net/attach.rs b/crates/spt-net/src/net/attach.rs index 9f75464a..5df5bd2d 100644 --- a/crates/spt-net/src/net/attach.rs +++ b/crates/spt-net/src/net/attach.rs @@ -282,7 +282,10 @@ mod tests { from_seq: 0, intent: AttachIntent::Control, endpoint_id: None, - gen: 0, code: None, seal_ceremony: false, }, + gen: 0, + code: None, + seal_ceremony: false, + }, AttachRecord::Output { seq: 3, data_b64: "aGk=".into(), @@ -291,10 +294,18 @@ mod tests { data_b64: "bHM=".into(), op_id: 42, }, - AttachRecord::Resize { rows: 40, cols: 120 }, - AttachRecord::Size { rows: 40, cols: 120 }, + AttachRecord::Resize { + rows: 40, + cols: 120, + }, + AttachRecord::Size { + rows: 40, + cols: 120, + }, AttachRecord::Exit { code: Some(0) }, - AttachRecord::Displaced { by: "hfenduleam".into() }, + AttachRecord::Displaced { + by: "hfenduleam".into(), + }, AttachRecord::SealCeremony { ceremony_id: 7, content_b64: "c2VhbCBtZQ==".into(), @@ -384,8 +395,16 @@ mod tests { } .encode_line(); let line = std::str::from_utf8(&plain_open).unwrap(); - for absent in ["payload_to_sign_b64", "fido2_node", "offer_enroll", "destination"] { - assert!(!line.contains(absent), "{absent} leaked onto a plain open: {line}"); + for absent in [ + "payload_to_sign_b64", + "fido2_node", + "offer_enroll", + "destination", + ] { + assert!( + !line.contains(absent), + "{absent} leaked onto a plain open: {line}" + ); } let plain_code = AttachRecord::SealCeremonyCode { ceremony_id: 7, @@ -397,7 +416,10 @@ mod tests { .encode_line(); let line = std::str::from_utf8(&plain_code).unwrap(); for absent in ["signature_hex", "enroll_pubkey_hex", "enroll_backend_kind"] { - assert!(!line.contains(absent), "{absent} leaked onto a plain code: {line}"); + assert!( + !line.contains(absent), + "{absent} leaked onto a plain code: {line}" + ); } // The proof frame carries signature BYTES and has no verdict-shaped // field to carry — the record is the proof, the daemon is the judge. @@ -412,7 +434,10 @@ mod tests { let line = std::str::from_utf8(&proof).unwrap(); assert!(line.contains("\"signature_hex\":\"ab01cd23\""), "{line}"); for verdictish in ["verified", "verdict", "outcome", "admitted"] { - assert!(!line.contains(verdictish), "a verdict-shaped field rode the proof: {line}"); + assert!( + !line.contains(verdictish), + "a verdict-shaped field rode the proof: {line}" + ); } } @@ -446,7 +471,10 @@ mod tests { from_seq: 0, intent: AttachIntent::Control, endpoint_id: None, - gen: 0, code: None, seal_ceremony: false, }], + gen: 0, + code: None, + seal_ceremony: false, + }], "omitted intent defaults to Control (N-1 operator)" ); assert_eq!(AttachIntent::default(), AttachIntent::Control); @@ -465,7 +493,10 @@ mod tests { from_seq: 0, intent: AttachIntent::Control, endpoint_id: Some("ling@gravity".into()), - gen: 0, code: None, seal_ceremony: false, }; + gen: 0, + code: None, + seal_ceremony: false, + }; let mut dec = AttachDecoder::new(); assert_eq!(dec.push(&remote.encode_line()), vec![remote.clone()]); assert!( @@ -479,7 +510,10 @@ mod tests { from_seq: 0, intent: AttachIntent::Control, endpoint_id: None, - gen: 0, code: None, seal_ceremony: false, }; + gen: 0, + code: None, + seal_ceremony: false, + }; assert!( !String::from_utf8_lossy(&local.encode_line()).contains("endpoint_id"), "local wire omits endpoint_id (N-1 byte-identity)" @@ -492,8 +526,20 @@ mod tests { // [unit->REQ-RCVIEW-1] the three intents round-trip distinctly on the wire. #[test] fn attach_intents_round_trip() { - for intent in [AttachIntent::Viewer, AttachIntent::Control, AttachIntent::Take] { - let r = AttachRecord::Request { session_id: 1, from_seq: 0, intent, endpoint_id: None , gen: 0, code: None, seal_ceremony: false }; + for intent in [ + AttachIntent::Viewer, + AttachIntent::Control, + AttachIntent::Take, + ] { + let r = AttachRecord::Request { + session_id: 1, + from_seq: 0, + intent, + endpoint_id: None, + gen: 0, + code: None, + seal_ceremony: false, + }; let mut dec = AttachDecoder::new(); assert_eq!(dec.push(&r.encode_line()), vec![r]); } @@ -634,8 +680,13 @@ mod tests { from_seq: 0, intent: AttachIntent::Take, endpoint_id: None, - gen: 0, code: None, seal_ceremony: false, }; - let displaced = AttachRecord::Displaced { by: "hfenduleam".into() }; + gen: 0, + code: None, + seal_ceremony: false, + }; + let displaced = AttachRecord::Displaced { + by: "hfenduleam".into(), + }; for r in [take, displaced] { let mut dec = AttachDecoder::new(); assert_eq!(dec.push(&r.encode_line()), vec![r]); diff --git a/crates/spt-net/src/net/codeseal.rs b/crates/spt-net/src/net/codeseal.rs index b1377a3c..871989c6 100644 --- a/crates/spt-net/src/net/codeseal.rs +++ b/crates/spt-net/src/net/codeseal.rs @@ -496,7 +496,10 @@ mod tests { // valid code; anything else is not a whole number of envelopes. let truncated = format!("{CODE_PREFIX}{}", &body[..body.len() - 4]); assert!(open(SEED_A, &truncated).is_none(), "{truncated}"); - assert!(open(SEED_B, &truncated).is_none(), "and for the other key too"); + assert!( + open(SEED_B, &truncated).is_none(), + "and for the other key too" + ); assert!( open(SEED_A, CODE_PREFIX).is_none(), "an empty body is not zero envelopes, it is malformed" @@ -511,7 +514,10 @@ mod tests { let (node, secret) = parts(); let code = seal(SEED_A, &node, &secret); assert!(open(SEED_B, &code).is_none(), "a non-member learns nothing"); - assert!(open(SEED_A, &code).is_some(), "and the right key still works"); + assert!( + open(SEED_A, &code).is_some(), + "and the right key still works" + ); } // [unit->REQ-KNOCK-CODE-SEALED] one flipped bit ANYWHERE in the envelope @@ -537,7 +543,11 @@ mod tests { "byte {i} was flipped and the code still opened" ); } - assert_eq!(envelope.len(), ENVELOPE_LEN, "the scan covered the whole envelope"); + assert_eq!( + envelope.len(), + ENVELOPE_LEN, + "the scan covered the whole envelope" + ); } // [unit->REQ-KNOCK-CODE-SEALED] every malformed shape returns the IDENTICAL @@ -552,10 +562,10 @@ mod tests { let refusals = [ String::new(), "not-a-code".to_string(), - body.to_string(), // no prefix - CODE_PREFIX.to_string(), // prefix only - format!("{CODE_PREFIX}!!!!"), // outside the alphabet - format!("{CODE_PREFIX}{body}aaaa"), // too long + body.to_string(), // no prefix + CODE_PREFIX.to_string(), // prefix only + format!("{CODE_PREFIX}!!!!"), // outside the alphabet + format!("{CODE_PREFIX}{body}aaaa"), // too long format!("{CODE_PREFIX}{}", &body[..body.len() - 4]), // too short ]; for r in &refusals { @@ -581,7 +591,12 @@ mod tests { let bytes = |c: &str| { data_encoding::BASE32_NOPAD - .decode(c.strip_prefix("sptkc_").unwrap().to_ascii_uppercase().as_bytes()) + .decode( + c.strip_prefix("sptkc_") + .unwrap() + .to_ascii_uppercase() + .as_bytes(), + ) .unwrap() }; let (ea, eb) = (bytes(&a), bytes(&b)); @@ -595,7 +610,11 @@ mod tests { "a one-byte plaintext delta must not yield a one-byte ciphertext delta (fixed-nonce keystream reuse): {ct_diffs} byte(s) differ" ); // And the nonce source itself moved, which is why. - assert_ne!(ea[..TAG_LEN], eb[..TAG_LEN], "the tag, and so the nonce, differs"); + assert_ne!( + ea[..TAG_LEN], + eb[..TAG_LEN], + "the tag, and so the nonce, differs" + ); } // [unit->REQ-KNOCK-CODE-SEALED] a code retyped in upper case still opens — @@ -634,7 +653,11 @@ mod tests { let candidates = [("home/current", SEED_B), ("home/prev", SEED_A)]; let opened = open_all_among(candidates, &code); - assert_eq!(opened.len(), 1, "exactly one candidate opens a one-envelope code"); + assert_eq!( + opened.len(), + 1, + "exactly one candidate opens a one-envelope code" + ); assert_eq!(opened[0].0, "home/prev", "and names WHICH key opened it"); assert_eq!(opened[0].1.secret, secret); @@ -658,11 +681,7 @@ mod tests { let code = seal_to_all(&[SEED_A, SEED_C], &node, &secret); // `home` has since rotated to SEED_B; `work` has not rotated at all. - let candidates = [ - ("home", SEED_B), - ("home", SEED_A), - ("work", SEED_C), - ]; + let candidates = [("home", SEED_B), ("home", SEED_A), ("work", SEED_C)]; let opened = open_all_among(candidates, &code); let labels: Vec<&str> = opened.iter().map(|(l, _)| *l).collect(); assert_eq!( diff --git a/crates/spt-net/src/net/endpoint.rs b/crates/spt-net/src/net/endpoint.rs index 26290dc1..9b8353b2 100644 --- a/crates/spt-net/src/net/endpoint.rs +++ b/crates/spt-net/src/net/endpoint.rs @@ -351,10 +351,14 @@ impl NetEndpoint { match families { BindFamilies::Dual => {} BindFamilies::V4Only => { - spt_proto::emit_line_err!("NET_FAMILY_GATE: binding IPv4-only (IPv6 unreachable or disabled)") + spt_proto::emit_line_err!( + "NET_FAMILY_GATE: binding IPv4-only (IPv6 unreachable or disabled)" + ) } BindFamilies::V6Only => { - spt_proto::emit_line_err!("NET_FAMILY_GATE: binding IPv6-only (IPv4 unreachable or disabled)") + spt_proto::emit_line_err!( + "NET_FAMILY_GATE: binding IPv6-only (IPv4 unreachable or disabled)" + ) } } let builder = match scope { diff --git a/crates/spt-net/src/net/knockmsg.rs b/crates/spt-net/src/net/knockmsg.rs index 370f0a48..953462e3 100644 --- a/crates/spt-net/src/net/knockmsg.rs +++ b/crates/spt-net/src/net/knockmsg.rs @@ -187,7 +187,11 @@ mod tests { let forged = br#"{"kind":"knock","id":"k-1","knocker":"doyle","target":"ling","knocker_node_claimed":"not-my-node"}"#; let back: KnockRecord = serde_json::from_slice(forged).expect("decodes"); assert_eq!(back.knocker_node_claimed.as_deref(), Some("not-my-node")); - assert_eq!(back.surfaces, Vec::::new(), "absent = every surface"); + assert_eq!( + back.surfaces, + Vec::::new(), + "absent = every surface" + ); assert!(!back.mutual); assert!(!back.as_user); } diff --git a/crates/spt-net/src/net/mesh/seedproof.rs b/crates/spt-net/src/net/mesh/seedproof.rs index 37bd6db5..b98780b6 100644 --- a/crates/spt-net/src/net/mesh/seedproof.rs +++ b/crates/spt-net/src/net/mesh/seedproof.rs @@ -141,8 +141,8 @@ impl SeedProofTranscript { /// between the two tags. // [impl->REQ-MESH-1] pub fn tag(&self, mk: &MembershipKey, prover: ProofRole) -> [u8; PROOF_TAG_LEN] { - let mut mac = HmacSha256::new_from_slice(mk.key_bytes()) - .expect("HMAC accepts any key length"); + let mut mac = + HmacSha256::new_from_slice(mk.key_bytes()).expect("HMAC accepts any key length"); mac.update(PROOF_DOMAIN); mac.update(prover.label()); // subnet_id is variable-length → length-prefix it. The rest are @@ -509,7 +509,10 @@ mod tests { let mutual = |dt: &[u8], at: &[u8]| { t.verify(&good, ProofRole::Dialer, dt) && t.verify(&good, ProofRole::Acceptor, at) }; - assert!(mutual(&dialer_tag, &acceptor_tag_good), "both prove → admit"); + assert!( + mutual(&dialer_tag, &acceptor_tag_good), + "both prove → admit" + ); assert!( !mutual(&dialer_tag, &acceptor_tag_bad), "one impostor → reject" @@ -613,7 +616,11 @@ mod tests { let f = SeedProofFrame::ProofSet { proofs: proofs.clone(), }; - assert_eq!(SeedProofFrame::decode(&f.encode()), Some(f), "round-trip {proofs:?}"); + assert_eq!( + SeedProofFrame::decode(&f.encode()), + Some(f), + "round-trip {proofs:?}" + ); } // Over the generation cap. diff --git a/crates/spt-net/src/net/notif.rs b/crates/spt-net/src/net/notif.rs index 03f07e7b..cf840353 100644 --- a/crates/spt-net/src/net/notif.rs +++ b/crates/spt-net/src/net/notif.rs @@ -138,7 +138,11 @@ mod tests { \"kind\":\"agent\",\"from_id\":\"ling\",\"body\":\"build done\",\"created_ms\":1000,\ \"dismissed\":true,\"seen\":[\"doyle\"],\"last_surfaced_ms\":5000}}\n"; let got = NotifDecoder::new().push(old); - assert_eq!(got, vec![NotifRecord::Row { row: r }], "old shape → defaults"); + assert_eq!( + got, + vec![NotifRecord::Row { row: r }], + "old shape → defaults" + ); } // [unit->REQ-HAZARD-WAN-ORIGIN-AUTH] records carry no origin field: a diff --git a/crates/spt-net/src/net/pairing/ntp.rs b/crates/spt-net/src/net/pairing/ntp.rs index d98e7da4..bca63d23 100644 --- a/crates/spt-net/src/net/pairing/ntp.rs +++ b/crates/spt-net/src/net/pairing/ntp.rs @@ -403,7 +403,11 @@ mod tests { let dead_v6_b: SocketAddr = "[2001:db8::1]:9".parse().unwrap(); let addrs = vec![dead_v6_a, dead_v6_b, v4_mock]; let got = query_first_reachable(addrs, Duration::from_millis(300)); - assert_eq!(got, Some(want), "iteration past dead v6 reaches the v4 answer"); + assert_eq!( + got, + Some(want), + "iteration past dead v6 reaches the v4 answer" + ); server.join().unwrap(); } @@ -461,14 +465,14 @@ mod tests { #[test] fn loud_fail_logs_only_on_transitions() { // ok -> fail: log UNCORRECTED - assert_eq!( - ntp_transition(false, None), - (true, Transition::Uncorrected) - ); + assert_eq!(ntp_transition(false, None), (true, Transition::Uncorrected)); // fail -> fail: silent (no spam) assert_eq!(ntp_transition(true, None), (true, Transition::Silent)); // fail -> ok: log RECOVERED - assert_eq!(ntp_transition(true, Some(5)), (false, Transition::Recovered)); + assert_eq!( + ntp_transition(true, Some(5)), + (false, Transition::Recovered) + ); // ok -> ok (corrected or agree): silent assert_eq!(ntp_transition(false, Some(5)), (false, Transition::Silent)); assert_eq!(ntp_transition(false, Some(0)), (false, Transition::Silent)); diff --git a/crates/spt-net/src/net/pairing/spake.rs b/crates/spt-net/src/net/pairing/spake.rs index 8f4ec0e2..b00e69bc 100644 --- a/crates/spt-net/src/net/pairing/spake.rs +++ b/crates/spt-net/src/net/pairing/spake.rs @@ -186,7 +186,10 @@ impl Initiator { /// at all when neither does, so the peer learns exactly what one ceremony always /// told it. // [impl->REQ-SUBNET-ADMIN-CODE-JOIN] - pub fn start_dual(transcript: PairingTranscript, code: &str) -> (Initiator, Initiator, Vec) { + pub fn start_dual( + transcript: PairingTranscript, + code: &str, + ) -> (Initiator, Initiator, Vec) { let mut seed = Zeroizing::new([0u8; 32]); OsRng.fill_bytes(&mut seed[..]); let (first, msg_a) = Self::start_with_rng(transcript.clone(), code, SeededRng::new(&seed)); @@ -492,7 +495,8 @@ mod tests { let t = transcript(&a, &b, "home", 1, 57_037_037); let (first, second, msg_a) = Initiator::start_dual(t.clone(), "314159"); // One message on the wire — the responder only ever answers this one. - let (_r1, msg_b, resp_tag) = Responder::respond(t.clone(), "314159", &msg_a).expect("respond"); + let (_r1, msg_b, resp_tag) = + Responder::respond(t.clone(), "314159", &msg_a).expect("respond"); // Either state finishes it, and both agree with the responder's key. let (p1, _) = first.finish(&msg_b, &resp_tag).expect("first finishes"); let (p2, _) = second.finish(&msg_b, &resp_tag).expect("second finishes"); @@ -533,14 +537,23 @@ mod tests { (Err(_), Ok(_)) => 2u8, _ => panic!("exactly one candidate must verify"), }; - assert_eq!(landed, expect_candidate, "{typed} lands on its own candidate"); + assert_eq!( + landed, expect_candidate, + "{typed} lands on its own candidate" + ); // Responder confirms against EITHER secret: the joiner's tag verifies on // the matching one and is refused by the other. - let init_tag = try1.map(|(_, t)| t).or_else(|_| try2.map(|(_, t)| t)).expect("one tag"); + let init_tag = try1 + .map(|(_, t)| t) + .or_else(|_| try2.map(|(_, t)| t)) + .expect("one tag"); let member_ok = r_member.confirm(&init_tag).is_ok(); let admin_ok = r_admin.confirm(&init_tag).is_ok(); - assert!(member_ok || admin_ok, "the ceremony completes on either key"); + assert!( + member_ok || admin_ok, + "the ceremony completes on either key" + ); assert_ne!(member_ok, admin_ok, "exactly one secret matches"); } } @@ -556,8 +569,14 @@ mod tests { let (first, second, msg_a) = Initiator::start_dual(t.clone(), "000000"); let (_rm, msg_b1, tag1) = Responder::respond(t.clone(), "111111", &msg_a).expect("member"); let (_ra, msg_b2, tag2) = Responder::respond(t, "999999", &msg_a).expect("admin"); - assert_eq!(first.finish(&msg_b1, &tag1).unwrap_err(), PairError::Confirm); - assert_eq!(second.finish(&msg_b2, &tag2).unwrap_err(), PairError::Confirm); + assert_eq!( + first.finish(&msg_b1, &tag1).unwrap_err(), + PairError::Confirm + ); + assert_eq!( + second.finish(&msg_b2, &tag2).unwrap_err(), + PairError::Confirm + ); } // [unit->REQ-HAZARD-PAIR-TRANSCRIPT-BIND] TAMPERED TAG: flipping a bit in the diff --git a/crates/spt-net/src/net/pairing/wire.rs b/crates/spt-net/src/net/pairing/wire.rs index 8f327457..98b892d0 100644 --- a/crates/spt-net/src/net/pairing/wire.rs +++ b/crates/spt-net/src/net/pairing/wire.rs @@ -374,9 +374,7 @@ async fn responder_admitted( let admin_responder = { // F4: Spake2 — msg_b + the responder's confirmation tag, plus the trailing // admin candidate when there is one. - let second = admin - .as_ref() - .map(|(_, msg_b2, tag2)| (&msg_b2[..], tag2)); + let second = admin.as_ref().map(|(_, msg_b2, tag2)| (&msg_b2[..], tag2)); write_frame(send, &enc_spake2(&msg_b, &responder_tag, second)).await?; admin.map(|(r, _, _)| r) }; @@ -1026,9 +1024,9 @@ fn decode_frame(body: &[u8]) -> Result { let field = c.field()?; let admin = match field.len() { 0 => None, - TOTP_SEED_LEN => Some( - <[u8; TOTP_SEED_LEN]>::try_from(field).expect("checked TOTP_SEED_LEN"), - ), + TOTP_SEED_LEN => { + Some(<[u8; TOTP_SEED_LEN]>::try_from(field).expect("checked TOTP_SEED_LEN")) + } n => { return Err(PairWireError::Protocol(format!( "admin seed is {n} bytes, want {TOTP_SEED_LEN}" @@ -1260,9 +1258,18 @@ mod tests { // The joiner ADOPTED the seed-holder's roster (REQ-MESH-2): the live // member is now its member, the tombstone propagated, and both were // stamped into the subnet it joined (not the empty wire subnet). - assert!(init_roster.is_member("home", "alpha"), "adopted live member"); - assert!(init_roster.is_tombstoned("home", "ghost"), "adopted tombstone"); - assert!(!init_roster.is_member("home", "ghost"), "tombstone dominates"); + assert!( + init_roster.is_member("home", "alpha"), + "adopted live member" + ); + assert!( + init_roster.is_tombstoned("home", "ghost"), + "adopted tombstone" + ); + assert!( + !init_roster.is_member("home", "ghost"), + "tombstone dominates" + ); assert_eq!( init_roster.find("home", "alpha").unwrap().label, "host-a", @@ -1296,7 +1303,15 @@ mod tests { .expect("connecting"); let subnets = subnet_store("home", seed, 1); let mut rate = PairingRateLimiter::new(); - let result = run_responder(&conn, resp_pub, &subnets, &RosterStore::default(), &mut rate, NOW).await; + let result = run_responder( + &conn, + resp_pub, + &subnets, + &RosterStore::default(), + &mut rate, + NOW, + ) + .await; conn.closed().await; // After a failed ceremony the slot is backed off (charged a failure). let retry = rate.begin("home", NOW); @@ -1368,7 +1383,15 @@ mod tests { let mut rate = PairingRateLimiter::new(); // A different ceremony already holds the slot. rate.begin("home", NOW).expect("pre-occupy slot"); - let result = run_responder(&conn, resp_pub, &subnets, &RosterStore::default(), &mut rate, NOW).await; + let result = run_responder( + &conn, + resp_pub, + &subnets, + &RosterStore::default(), + &mut rate, + NOW, + ) + .await; conn.closed().await; result }); @@ -1428,7 +1451,15 @@ mod tests { .expect("connecting"); let subnets = subnet_store("home", seed, 1); let mut rate = PairingRateLimiter::new(); - let result = run_responder(&conn, resp_pub, &subnets, &RosterStore::default(), &mut rate, NOW).await; + let result = run_responder( + &conn, + resp_pub, + &subnets, + &RosterStore::default(), + &mut rate, + NOW, + ) + .await; conn.closed().await; result }); @@ -1483,7 +1514,15 @@ mod tests { .expect("connecting"); let subnets = subnet_store("home", seed, 1); // only "home" exists let mut rate = PairingRateLimiter::new(); - let result = run_responder(&conn, resp_pub, &subnets, &RosterStore::default(), &mut rate, NOW).await; + let result = run_responder( + &conn, + resp_pub, + &subnets, + &RosterStore::default(), + &mut rate, + NOW, + ) + .await; conn.closed().await; result }); @@ -1546,9 +1585,16 @@ mod tests { .await .expect("connecting"); let mut rate = PairingRateLimiter::new(); - run_responder(&conn, resp_pub, &subnets, &RosterStore::default(), &mut rate, NOW) - .await - .expect("responder pairs"); + run_responder( + &conn, + resp_pub, + &subnets, + &RosterStore::default(), + &mut rate, + NOW, + ) + .await + .expect("responder pairs"); conn.closed().await; }); @@ -1602,9 +1648,16 @@ mod tests { .expect("connecting"); let subnets = subnet_store("home", seed, 2); let mut rate = PairingRateLimiter::new(); - let outcome = run_responder(&conn, resp_pub, &subnets, &RosterStore::default(), &mut rate, NOW) - .await - .expect("responder pairs"); + let outcome = run_responder( + &conn, + resp_pub, + &subnets, + &RosterStore::default(), + &mut rate, + NOW, + ) + .await + .expect("responder pairs"); conn.closed().await; outcome }); @@ -1699,7 +1752,11 @@ mod tests { enc_announce(42), enc_spake1(b"msg-a-bytes"), enc_spake2(b"msg-b", &[7u8; TAG_LEN], None), - enc_spake2(b"msg-b", &[7u8; TAG_LEN], Some((b"msg-b2", &[8u8; TAG_LEN]))), + enc_spake2( + b"msg-b", + &[7u8; TAG_LEN], + Some((b"msg-b2", &[8u8; TAG_LEN])), + ), enc_confirm(&[9u8; TAG_LEN]), enc_done(true), enc_done(false), @@ -1757,7 +1814,16 @@ mod tests { stamp: "9".into(), }]; - match decode_frame(&enc_seed(&[1u8; TOTP_SEED_LEN], 3, &members, &tombs, None, None)).expect("decode") { + match decode_frame(&enc_seed( + &[1u8; TOTP_SEED_LEN], + 3, + &members, + &tombs, + None, + None, + )) + .expect("decode") + { Frame::Seed { seed, epoch, @@ -1771,7 +1837,10 @@ mod tests { assert_eq!(roster[0].subnet, "", "subnet implicit on the wire"); assert_eq!(roster[0].pubkey_hex, "aa"); assert_eq!(roster[0].label, "host-a"); - assert_eq!(roster[0].address, Some(serde_json::json!({"addr": "1.2.3.4:5"}))); + assert_eq!( + roster[0].address, + Some(serde_json::json!({"addr": "1.2.3.4:5"})) + ); assert_eq!(roster[0].lease_epoch, 7); assert_eq!(roster[1].address, None, "absent address stays None"); assert_eq!(tombstones.len(), 1); @@ -1781,7 +1850,9 @@ mod tests { } // Empty roster round-trips. - match decode_frame(&enc_seed(&[2u8; TOTP_SEED_LEN], 1, &[], &[], None, None)).expect("decode") { + match decode_frame(&enc_seed(&[2u8; TOTP_SEED_LEN], 1, &[], &[], None, None)) + .expect("decode") + { Frame::Seed { roster, tombstones, .. } => { @@ -1808,7 +1879,10 @@ mod tests { bad.extend_from_slice(&[4u8; TOTP_SEED_LEN]); bad.extend_from_slice(&1u64.to_be_bytes()); bad.extend_from_slice(&1u32.to_be_bytes()); - assert!(matches!(decode_frame(&bad), Err(PairWireError::Protocol(_)))); + assert!(matches!( + decode_frame(&bad), + Err(PairWireError::Protocol(_)) + )); } // [unit->REQ-SUBNET-ADMIN-SEED-REPLICATION] the admin seed rides the Seed @@ -1976,13 +2050,15 @@ mod tests { // The upgraded seed-holder answers twice and frames both, member first. let (member_r, msg_b1, tag1) = Responder::respond(t.clone(), MEMBER, &msg_a).expect("member respond"); - let (_admin_r, msg_b2, tag2) = - Responder::respond(t, ADMIN, &msg_a).expect("admin respond"); + let (_admin_r, msg_b2, tag2) = Responder::respond(t, ADMIN, &msg_a).expect("admin respond"); let framed = enc_spake2(&msg_b1, &tag1, Some((&msg_b2[..], &tag2))); // The legacy parse sees the member candidate and nothing else... let (seen_msg_b, seen_tag) = legacy_dec_spake2(&framed); - assert_eq!(seen_msg_b, msg_b1, "the leading candidate is the member key's"); + assert_eq!( + seen_msg_b, msg_b1, + "the leading candidate is the member key's" + ); assert_eq!(seen_tag, tag1); // ...and the ceremony completes, both ways. let (_paired, init_tag) = legacy diff --git a/crates/spt-net/src/net/presencemsg.rs b/crates/spt-net/src/net/presencemsg.rs index 347d1167..861103fe 100644 --- a/crates/spt-net/src/net/presencemsg.rs +++ b/crates/spt-net/src/net/presencemsg.rs @@ -265,7 +265,8 @@ mod tests { let back: PresenceRecord = serde_json::from_slice(&line[..line.len() - 1]).unwrap(); assert_eq!(back, rec); - let future = br#"{"kind":"presence","id":"p-2","asker":"d","target":"l","future_field":42}"#; + let future = + br#"{"kind":"presence","id":"p-2","asker":"d","target":"l","future_field":42}"#; let back: PresenceRecord = serde_json::from_slice(future).expect("unknown fields ignored"); assert_eq!(back.id, "p-2"); } @@ -305,7 +306,10 @@ mod tests { let line = PresenceReply::of(Presence::Busy).encode_line(); let v: serde_json::Value = serde_json::from_slice(&line[..line.len() - 1]).expect("valid json line"); - assert_eq!(v.get("presence").and_then(|p| p.as_str()), Some(token::BUSY)); + assert_eq!( + v.get("presence").and_then(|p| p.as_str()), + Some(token::BUSY) + ); assert_eq!( v.as_object().map(|o| o.len()), Some(1), diff --git a/crates/spt-net/src/net/registry.rs b/crates/spt-net/src/net/registry.rs index f2e6a228..ba6e3089 100644 --- a/crates/spt-net/src/net/registry.rs +++ b/crates/spt-net/src/net/registry.rs @@ -606,10 +606,11 @@ pub fn resource_projection( if !instance.status.routable() { continue; } - let node_label = instance - .node_label - .clone() - .or_else(|| node_labels.get(instance.node.as_str()).map(|l| l.to_string())); + let node_label = instance.node_label.clone().or_else(|| { + node_labels + .get(instance.node.as_str()) + .map(|l| l.to_string()) + }); out.push(ResourceRow { endpoint_id: id.to_string(), node: instance.node.clone(), @@ -1143,8 +1144,7 @@ pub struct RestGoal { /// operator's override when the advisory is wrong. // [impl->REQ-REST-VERB-ROUTING] pub fn select_rest_target(candidates: &[(String, Status)], goal: RestGoal) -> RestTarget { - let live: Vec<&(String, Status)> = - candidates.iter().filter(|(_, s)| s.routable()).collect(); + let live: Vec<&(String, Status)> = candidates.iter().filter(|(_, s)| s.routable()).collect(); if live.is_empty() { return RestTarget::NotFound; } @@ -1206,7 +1206,10 @@ mod tests { #[test] fn node_routability_keeps_unknown_distinct_from_offline() { let mut reg = SubnetRegistry::new(); - assert!(reg.node_routability().is_empty(), "an empty registry knows nothing about anyone"); + assert!( + reg.node_routability().is_empty(), + "an empty registry knows nothing about anyone" + ); reg.merge_instance("live-ep", inst("up", Status::Active, 1)); reg.merge_instance("dead-ep", inst("down", Status::Offline, 1)); @@ -1216,8 +1219,16 @@ mod tests { let r = reg.node_routability(); assert_eq!(r.get("up"), Some(&true), "a routable row reads live"); - assert_eq!(r.get("down"), Some(&false), "only-offline rows read offline"); - assert_eq!(r.get("mixed"), Some(&true), "rows OR: one live row carries the node"); + assert_eq!( + r.get("down"), + Some(&false), + "only-offline rows read offline" + ); + assert_eq!( + r.get("mixed"), + Some(&true), + "rows OR: one live row carries the node" + ); assert_eq!( r.get("stranger"), None, @@ -1280,7 +1291,10 @@ mod tests { // the silent-wire-skew guard. let old: Instance = serde_json::from_str(r#"{"node":"n1","status":"Active","epoch":1}"#).unwrap(); - assert!(old.bound, "an N-1 row defaults to BOUND (no phantom unbound)"); + assert!( + old.bound, + "an N-1 row defaults to BOUND (no phantom unbound)" + ); assert_eq!(old.controller_node, None, "N-1 → no controller"); assert!(!old.harness_only, "N-1 → not harness-only"); @@ -1294,8 +1308,14 @@ mod tests { ..full.clone() }; let pjson = serde_json::to_string(&plain).unwrap(); - assert!(!pjson.contains("controller_node"), "None controller skip-serializes"); - assert!(!pjson.contains("harness_only"), "false harness_only skip-serializes"); + assert!( + !pjson.contains("controller_node"), + "None controller skip-serializes" + ); + assert!( + !pjson.contains("harness_only"), + "false harness_only skip-serializes" + ); } // [unit->REQ-GOSSIP-ADAPTER-PROJECTS] #4: the de-faking gossip fields @@ -1328,8 +1348,14 @@ mod tests { let plain = inst("n1", Status::Active, 1); let pjson = serde_json::to_string(&plain).unwrap(); assert!(!pjson.contains("adapter"), "None adapter skip-serializes"); - assert!(!pjson.contains("recent_projects"), "empty projects skip-serializes"); - assert!(!pjson.contains("controlled"), "false controlled skip-serializes"); + assert!( + !pjson.contains("recent_projects"), + "empty projects skip-serializes" + ); + assert!( + !pjson.contains("controlled"), + "false controlled skip-serializes" + ); } // [unit->REQ-INST-7] distinct nodes for one id coexist as separate instances. @@ -1460,9 +1486,19 @@ mod tests { 1, "only the aged remote Offline row evicts" ); - let nodes: Vec<&str> = reg.instances("ling").iter().map(|i| i.node.as_str()).collect(); - assert!(!nodes.contains(&"faraway"), "aged remote Offline ghost evicted"); - assert!(nodes.contains(&"recent"), "fresh remote Offline row survives its grace"); + let nodes: Vec<&str> = reg + .instances("ling") + .iter() + .map(|i| i.node.as_str()) + .collect(); + assert!( + !nodes.contains(&"faraway"), + "aged remote Offline ghost evicted" + ); + assert!( + nodes.contains(&"recent"), + "fresh remote Offline row survives its grace" + ); assert!(nodes.contains(&own), "own Offline row never decays"); } @@ -1488,10 +1524,15 @@ mod tests { "a revived (routable) row is never evicted" ); assert!( - reg.instances("ling").iter().any(|i| i.node == "peer" && i.status == Status::Active), + reg.instances("ling") + .iter() + .any(|i| i.node == "peer" && i.status == Status::Active), "the revived row survives" ); - assert!(reg.offline_since.is_empty(), "the revived row's offline_since stamp cleared"); + assert!( + reg.offline_since.is_empty(), + "the revived row's offline_since stamp cleared" + ); } // The receiver-observed offline_since side-map is SELF-PRUNING: it stays a @@ -1508,12 +1549,20 @@ mod tests { ("c", own, Status::Offline), // own — never stamped ]); reg.evict_aged_offline(1_000, GRACE, own); - assert_eq!(reg.offline_since.len(), 2, "both REMOTE Offline rows stamped, own excluded"); + assert_eq!( + reg.offline_since.len(), + 2, + "both REMOTE Offline rows stamped, own excluded" + ); // n1 revives → its stamp prunes on the next sweep. reg.merge_instance("a", inst("n1", Status::Active, 2)); reg.evict_aged_offline(1_500, GRACE, own); - assert_eq!(reg.offline_since.len(), 1, "a revived row's stamp is pruned"); + assert_eq!( + reg.offline_since.len(), + 1, + "a revived row's stamp is pruned" + ); // Whole-node eviction (node-silence trigger (a)) removes n2's row; the next // Offline sweep drops its stamp for free — no explicit side-map purge needed. @@ -1569,9 +1618,14 @@ mod tests { // Past the grace: every aged Offline ghost evicts; the routable row stays. let evicted = reg.evict_aged_offline(1_000 + GRACE + 1, GRACE, own); - assert_eq!(evicted, 3, "all three aged Offline ghosts evicted (bounded snapshot)"); + assert_eq!( + evicted, 3, + "all three aged Offline ghosts evicted (bounded snapshot)" + ); assert!( - reg.instances("keep").iter().any(|i| i.node == "farm" && i.status == Status::Active), + reg.instances("keep") + .iter() + .any(|i| i.node == "farm" && i.status == Status::Active), "the live routable row is untouched" ); assert_eq!( @@ -1580,7 +1634,10 @@ mod tests { "the routable count is unchanged by Offline-ghost eviction — composes with \ REQ-SUBNET-COUNT-ROUTABLE" ); - assert!(reg.offline_since.is_empty(), "no residual stamps after the ghosts are reaped"); + assert!( + reg.offline_since.is_empty(), + "no residual stamps after the ghosts are reaped" + ); } fn count_routable(reg: &SubnetRegistry) -> usize { @@ -1750,7 +1807,10 @@ mod tests { reg.endpoint_ids().next().is_none(), "a node label creates no endpoint row" ); - assert_eq!(reg.node_labels().collect::>(), vec![("n1", "OLDHOST")]); + assert_eq!( + reg.node_labels().collect::>(), + vec![("n1", "OLDHOST")] + ); // Lease: strictly-greater epoch wins; a lagging epoch is stale. assert_eq!( @@ -1761,7 +1821,10 @@ mod tests { reg.merge_node_label("n1", "OLDHOST".into(), 1), MergeOutcome::Stale ); - assert_eq!(reg.node_labels().collect::>(), vec![("n1", "NEWHOST")]); + assert_eq!( + reg.node_labels().collect::>(), + vec![("n1", "NEWHOST")] + ); // Silence ghost-decay does NOT drop the label — an offline-but-trusted // member keeps its NAME (evict_nodes touches routable instance rows only). @@ -1777,7 +1840,11 @@ mod tests { ); // Explicit prune DOES forget the label. - assert_eq!(reg.evict_node_labels(|node| node == "n1"), 1, "prune forgets"); + assert_eq!( + reg.evict_node_labels(|node| node == "n1"), + 1, + "prune forgets" + ); assert!(reg.node_labels().next().is_none()); // Serde: roundtrips; a pre-M8 snapshot (no node_labels key) parses clean. @@ -1984,7 +2051,11 @@ mod tests { let rows = resource_projection(®, |_| false); let by = |id: &str| rows.iter().find(|r| r.endpoint_id == id).unwrap(); - assert_eq!(by("ling").node_label.as_deref(), Some("HOST1"), "instance label"); + assert_eq!( + by("ling").node_label.as_deref(), + Some("HOST1"), + "instance label" + ); assert_eq!(by("oak").node_label.as_deref(), Some("HOST2"), "map fill"); assert_eq!(by("bare").node_label, None, "no label known"); @@ -1994,7 +2065,11 @@ mod tests { "HOST1 (n1deadbe…)" ); assert_eq!(node_label_display("n3face", None), "n3face…"); - assert_eq!(node_label_display("n3face", Some(" ")), "n3face…", "blank → bare"); + assert_eq!( + node_label_display("n3face", Some(" ")), + "n3face…", + "blank → bare" + ); } // [unit->REQ-ENDPOINT-LIST-NODE-GROUPED] the advertised endpoint_type rides the @@ -2029,8 +2104,16 @@ mod tests { let rows = resource_projection(®, |_| false); let by = |id: &str| rows.iter().find(|r| r.endpoint_id == id).unwrap(); - assert_eq!(by("agent").endpoint_type.as_deref(), Some("live_agent"), "gossiped type threaded"); - assert_eq!(by("legacy").endpoint_type, None, "pre-field row stays None (renders '-')"); + assert_eq!( + by("agent").endpoint_type.as_deref(), + Some("live_agent"), + "gossiped type threaded" + ); + assert_eq!( + by("legacy").endpoint_type, + None, + "pre-field row stays None (renders '-')" + ); } // [unit->REQ-GOSSIP-ADAPTER-PROJECTS] #4: the de-faking datums ride the projection @@ -2054,11 +2137,26 @@ mod tests { let rows = resource_projection(®, |_| false); let by = |id: &str| rows.iter().find(|r| r.endpoint_id == id).unwrap(); - assert_eq!(by("agent").adapter.as_deref(), Some("claude-spt:doyle"), "adapter threaded"); - assert_eq!(by("agent").recent_projects, vec!["spt-core", "owl"], "projects threaded"); + assert_eq!( + by("agent").adapter.as_deref(), + Some("claude-spt:doyle"), + "adapter threaded" + ); + assert_eq!( + by("agent").recent_projects, + vec!["spt-core", "owl"], + "projects threaded" + ); assert!(by("agent").controlled, "controlled threaded"); - assert_eq!(by("legacy").adapter, None, "pre-field adapter None (renders '-')"); - assert!(by("legacy").recent_projects.is_empty(), "pre-field projects empty"); + assert_eq!( + by("legacy").adapter, + None, + "pre-field adapter None (renders '-')" + ); + assert!( + by("legacy").recent_projects.is_empty(), + "pre-field projects empty" + ); assert!(!by("legacy").controlled, "pre-field not controlled"); } @@ -2596,17 +2694,26 @@ mod tests { rows.iter().map(|(n, s)| (n.to_string(), *s)).collect() } fn wake_goal() -> RestGoal { - RestGoal { target: Status::Active, kind: GoalKind::Exists } + RestGoal { + target: Status::Active, + kind: GoalKind::Exists, + } } fn suspend_goal() -> RestGoal { - RestGoal { target: Status::Suspended, kind: GoalKind::Forall } + RestGoal { + target: Status::Suspended, + kind: GoalKind::Forall, + } } // [unit->REQ-REST-VERB-ROUTING] WAKE (∃-goal, target=Active): the full table. #[test] fn select_rest_target_wake_goal_satisfaction() { // 0 candidates -> NotFound. - assert_eq!(select_rest_target(&cands(&[]), wake_goal()), RestTarget::NotFound); + assert_eq!( + select_rest_target(&cands(&[]), wake_goal()), + RestTarget::NotFound + ); // 1 Active -> already satisfied -> NoOp naming it. assert_eq!( select_rest_target(&cands(&[("a", Status::Active)]), wake_goal()), diff --git a/crates/spt-net/src/net/replicate.rs b/crates/spt-net/src/net/replicate.rs index b049e4e1..1c3d9cc0 100644 --- a/crates/spt-net/src/net/replicate.rs +++ b/crates/spt-net/src/net/replicate.rs @@ -264,7 +264,8 @@ mod tests { let inst_line = inst.encode_line(); let label_line = label.encode_line(); assert_eq!( - serde_json::from_slice::(&inst_line[..inst_line.len() - 1]).unwrap(), + serde_json::from_slice::(&inst_line[..inst_line.len() - 1]) + .unwrap(), inst ); assert_eq!( @@ -283,7 +284,11 @@ mod tests { // skips the node-label row (an older fleet node never wedges). let mut old = LineDecoder::new(); let got = old.push(&wire); - assert_eq!(got.len(), 1, "only the instance row decodes for an old peer"); + assert_eq!( + got.len(), + 1, + "only the instance row decodes for an old peer" + ); assert_eq!(got[0].endpoint_id, "doyle"); } diff --git a/crates/spt-net/src/net/sealmsg.rs b/crates/spt-net/src/net/sealmsg.rs index 50ce8cf0..afae84e4 100644 --- a/crates/spt-net/src/net/sealmsg.rs +++ b/crates/spt-net/src/net/sealmsg.rs @@ -138,7 +138,10 @@ mod tests { }; let line = r.encode_line(); let mut dec = SealFeedDecoder::new(); - assert!(dec.push(&line[..line.len() / 2]).is_empty(), "no newline, no record"); + assert!( + dec.push(&line[..line.len() / 2]).is_empty(), + "no newline, no record" + ); assert_eq!(dec.push(&line[line.len() / 2..]), vec![r]); } @@ -189,7 +192,9 @@ mod tests { json.as_object_mut() .unwrap() .insert("origin_node".into(), "evil".into()); - json.as_object_mut().unwrap().insert("node".into(), "evil".into()); + json.as_object_mut() + .unwrap() + .insert("node".into(), "evil".into()); let decoded: SealWireRecord = serde_json::from_value(json).unwrap(); assert_eq!(decoded, r, "forged fields are inert unknowns"); } diff --git a/crates/spt-net/src/net/wanmsg.rs b/crates/spt-net/src/net/wanmsg.rs index 7edb9ba1..2d770049 100644 --- a/crates/spt-net/src/net/wanmsg.rs +++ b/crates/spt-net/src/net/wanmsg.rs @@ -379,7 +379,8 @@ mod tests { // A W2b-era record: sender stamped, origin absent. The mixture must // decode cleanly rather than requiring the two to travel together. - let w2b = br#"{"target":"ling","from":"doyle","body":"x","op_id":"n:1","sender_proven":"doyle"}"#; + let w2b = + br#"{"target":"ling","from":"doyle","body":"x","op_id":"n:1","sender_proven":"doyle"}"#; let decoded: WanMessage = serde_json::from_slice(w2b).unwrap(); assert_eq!(decoded.sender_proven.as_deref(), Some("doyle")); assert_eq!(decoded.sender_origin, None); diff --git a/crates/spt-poolguard/src/lib.rs b/crates/spt-poolguard/src/lib.rs index 3afb799b..bf9c8e8a 100644 --- a/crates/spt-poolguard/src/lib.rs +++ b/crates/spt-poolguard/src/lib.rs @@ -440,9 +440,9 @@ pub fn git_lane_state(repo: &Path, claim: &LaneClaim) -> LaneState { /// The ref a lane is measured as landed against, first that resolves. fn integration_head(repo: &Path) -> Option<(String, String)> { - ["origin/main", "main"] - .into_iter() - .find_map(|r| git_out(repo, &["rev-parse", "--verify", "--quiet", r]).map(|s| (r.into(), s))) + ["origin/main", "main"].into_iter().find_map(|r| { + git_out(repo, &["rev-parse", "--verify", "--quiet", r]).map(|s| (r.into(), s)) + }) } fn short(sha: &str) -> String { @@ -1141,9 +1141,9 @@ mod tests { label: "finished".into(), pid: DEAD_PID, started_at: Some(1), - branch: None, - base: None, - }); + branch: None, + base: None, + }); stamp(d.path(), &tree.path().to_string_lossy(), dead.clone()); assert!( matches!(classify(d.path(), 0), PoolState::Owned { .. }), @@ -1243,7 +1243,9 @@ mod tests { ); // Control first: with NO ancestry oracle this same stamp is a takeover. // Without this arm the test could pass on a guard that refuses always. - match decide_with(p.path(), Path::new("/trees/b"), None, &|_| LaneState::Unknown) { + match decide_with(p.path(), Path::new("/trees/b"), None, &|_| { + LaneState::Unknown + }) { Verdict::Takeover { .. } => {} other => panic!("control: an unreadable lane keeps the old behaviour, got {other:?}"), } @@ -1310,7 +1312,11 @@ mod tests { ProcIdentity::Present(b) => Some(b), _ => None, }; - stamp(p.path(), "/trees/a", Some(identified("still-building", me, born))); + stamp( + p.path(), + "/trees/a", + Some(identified("still-building", me, born)), + ); match decide_with(p.path(), Path::new("/trees/b"), None, &settled) { Verdict::Refuse { evidence, .. } => assert!( evidence.contains(&me.to_string()), @@ -1398,7 +1404,9 @@ mod tests { let arms: Vec<(&str, Verdict)> = vec![ ("unclaimed foreign", { stamp(p.path(), "/trees/a", None); - decide_with(p.path(), Path::new("/trees/b"), None, &|_| LaneState::Unknown) + decide_with(p.path(), Path::new("/trees/b"), None, &|_| { + LaneState::Unknown + }) }), ("dead holder over an unlanded lane", { stamp( diff --git a/crates/spt-procident/src/lib.rs b/crates/spt-procident/src/lib.rs index aa2cd377..6a1cd9d4 100644 --- a/crates/spt-procident/src/lib.rs +++ b/crates/spt-procident/src/lib.rs @@ -317,11 +317,13 @@ pub fn process_started_at(pid: u32) -> Option { return None; } let mut created = FileTime::default(); - let (mut exit, mut kernel, mut user) = - (FileTime::default(), FileTime::default(), FileTime::default()); - let ok = unsafe { - GetProcessTimes(handle, &mut created, &mut exit, &mut kernel, &mut user) - }; + let (mut exit, mut kernel, mut user) = ( + FileTime::default(), + FileTime::default(), + FileTime::default(), + ); + let ok = + unsafe { GetProcessTimes(handle, &mut created, &mut exit, &mut kernel, &mut user) }; unsafe { CloseHandle(handle); } @@ -568,9 +570,13 @@ mod pinned_proc_tests { fn exited_pid() -> u32 { let mut child = if cfg!(windows) { - std::process::Command::new("cmd").args(["/C", "exit"]).spawn() + std::process::Command::new("cmd") + .args(["/C", "exit"]) + .spawn() } else { - std::process::Command::new("sh").args(["-c", "exit"]).spawn() + std::process::Command::new("sh") + .args(["-c", "exit"]) + .spawn() } .expect("spawn a short-lived child to make a corpse of"); let pid = child.id(); @@ -648,7 +654,10 @@ mod pinned_proc_tests { #[test] fn an_unstamped_pin_degrades_to_bare_pid_in_both_directions() { let alive = PinnedProc::from_stamp(std::process::id(), None); - assert!(!alive.is_stamped(), "the pin must admit it carries no stamp"); + assert!( + !alive.is_stamped(), + "the pin must admit it carries no stamp" + ); assert!( !alive.provably_gone(), "unstamped and present: no verdict of death may be invented" diff --git a/crates/spt-proto/src/emit.rs b/crates/spt-proto/src/emit.rs index 6ccd60ed..b28e1aad 100644 --- a/crates/spt-proto/src/emit.rs +++ b/crates/spt-proto/src/emit.rs @@ -492,7 +492,10 @@ mod tests { got, b"SUBSCRIBE_DECISION:endpoint-7: seated\n", "a short write must cost a late tail, never a lost one" ); - assert!(got.ends_with(b"\n"), "the terminator must survive the retry"); + assert!( + got.ends_with(b"\n"), + "the terminator must survive the retry" + ); // The count is REPORTED, never asserted: more than one call here is the // ruled behaviour of write_all, not a defect. println!( @@ -508,8 +511,11 @@ mod tests { #[test] fn a_short_writing_sink_receives_a_complete_block_too() { let mut w = ShortWritingWriter::new(5); - emit_block!(&mut w, "SERVICE_STARTUP_FAULT:svc: 3 exits\n tail one\n tail two") - .expect("write"); + emit_block!( + &mut w, + "SERVICE_STARTUP_FAULT:svc: 3 exits\n tail one\n tail two" + ) + .expect("write"); assert_eq!( w.joined(), b"SERVICE_STARTUP_FAULT:svc: 3 exits\n tail one\n tail two\n" diff --git a/crates/spt-proto/src/envelope.rs b/crates/spt-proto/src/envelope.rs index 64880c29..ff50f8db 100644 --- a/crates/spt-proto/src/envelope.rs +++ b/crates/spt-proto/src/envelope.rs @@ -227,7 +227,10 @@ mod tests { #[test] fn body_escape_is_cr_linesafe() { let escaped = event_body_escape("hey\r\nthere\rworld"); - assert!(!escaped.contains('\r'), "no raw CR survives into the EVENT line"); + assert!( + !escaped.contains('\r'), + "no raw CR survives into the EVENT line" + ); assert_eq!(escaped, "hey
there
world"); assert_eq!(event_body_unescape(&escaped), "hey\nthere\nworld"); // A trailing CRLF (the `echo | spt send` case) doesn't leave a stray CR. @@ -246,8 +249,14 @@ mod tests { #[test] fn attr_escape_is_line_safe() { let escaped = event_attr_escape("hey\r\nthere\rworld\nagain"); - assert!(!escaped.contains('\n'), "no raw LF survives into the EVENT line: {escaped}"); - assert!(!escaped.contains('\r'), "no raw CR survives into the EVENT line: {escaped}"); + assert!( + !escaped.contains('\n'), + "no raw LF survives into the EVENT line: {escaped}" + ); + assert!( + !escaped.contains('\r'), + "no raw CR survives into the EVENT line: {escaped}" + ); assert_eq!(escaped, "hey there world again"); assert_eq!( event_attr_unescape(&escaped), diff --git a/crates/spt-proto/src/event.rs b/crates/spt-proto/src/event.rs index 029ba636..b753d01f 100644 --- a/crates/spt-proto/src/event.rs +++ b/crates/spt-proto/src/event.rs @@ -277,8 +277,7 @@ pub const EVENT_ATTR_SEAL: &str = "seal"; /// two lanes at one seam is a drift pair, and this is the shape that does not /// become one. // [impl->REQ-TRUST-WARNING-ENVELOPE] -pub const RECEIVER_COMPOSED_ATTRS: &[&str] = - &[EVENT_ATTR_MNEMONICS_JSON, EVENT_ATTR_TRUST_WARNING]; +pub const RECEIVER_COMPOSED_ATTRS: &[&str] = &[EVENT_ATTR_MNEMONICS_JSON, EVENT_ATTR_TRUST_WARNING]; /// Is `key` safe to re-emit as an attribute NAME? /// diff --git a/crates/spt-proto/src/lib.rs b/crates/spt-proto/src/lib.rs index 3331f368..0c332e5a 100644 --- a/crates/spt-proto/src/lib.rs +++ b/crates/spt-proto/src/lib.rs @@ -21,6 +21,6 @@ pub mod event; pub mod id; pub mod identity; pub mod ioevent; -pub mod shortform; pub mod payload; +pub mod shortform; pub mod version; diff --git a/crates/spt-proto/src/shortform.rs b/crates/spt-proto/src/shortform.rs index eaa8ed5a..e71de67d 100644 --- a/crates/spt-proto/src/shortform.rs +++ b/crates/spt-proto/src/shortform.rs @@ -463,7 +463,10 @@ mod seal_tests { assert_eq!(got.len(), 2, "two pairs, two ceremonies: {got:?}"); assert_eq!(got[0].text, "first text"); assert_eq!(got[1].text, "second text"); - assert!(got.iter().all(|m| !m.bare), "neither came from a bare marker"); + assert!( + got.iter().all(|m| !m.bare), + "neither came from a bare marker" + ); assert!( !got.iter().any(|m| m.text.contains("middle")), "the text BETWEEN pairs belongs to neither seal: {got:?}" @@ -507,7 +510,10 @@ mod seal_tests { fn an_empty_pair_mints_nothing_and_refuses_nothing() { assert!(parse_seal_mints(";;;;").is_empty()); assert!(parse_seal_mints("text ;;;; more").is_empty()); - assert!(parse_seal_mints(";; ;;").is_empty(), "whitespace-only is empty too"); + assert!( + parse_seal_mints(";; ;;").is_empty(), + "whitespace-only is empty too" + ); } // [unit->REQ-IO-SEAL-SHORTFORM-GRAMMAR] an empty pair among real ones is @@ -517,7 +523,11 @@ mod seal_tests { #[test] fn an_empty_pair_does_not_disturb_the_pairs_around_it() { let got = texts(";;alpha;; ;;;; ;;beta;;"); - assert_eq!(got, vec!["alpha", "beta"], "the empty pair vanished cleanly: {got:?}"); + assert_eq!( + got, + vec!["alpha", "beta"], + "the empty pair vanished cleanly: {got:?}" + ); } // [unit->REQ-IO-SEAL-SHORTFORM-GRAMMAR] THE SHARED SUPPRESSION SEAM (ruling @@ -527,9 +537,12 @@ mod seal_tests { #[test] fn a_quoted_seal_marker_mints_nothing() { assert!(parse_seal_mints("write `;;text;;` to seal").is_empty()); - assert!(parse_seal_mints("``` + assert!(parse_seal_mints( + "``` ;;text;; -```").is_empty()); +```" + ) + .is_empty()); } // [unit->REQ-IO-SEAL-SHORTFORM-GRAMMAR] suppression is SCOPED here too: a @@ -548,9 +561,16 @@ mod seal_tests { // text is worse than no seal. #[test] fn the_sealed_text_is_carried_verbatim() { - let got = texts(";; spaced and `ticked` -multiline ;;"); - assert_eq!(got, vec![" spaced and `ticked` -multiline "]); + let got = texts( + ";; spaced and `ticked` +multiline ;;", + ); + assert_eq!( + got, + vec![ + " spaced and `ticked` +multiline " + ] + ); } } diff --git a/crates/spt-runtime/src/manifest.rs b/crates/spt-runtime/src/manifest.rs index 047b6949..b235da3b 100644 --- a/crates/spt-runtime/src/manifest.rs +++ b/crates/spt-runtime/src/manifest.rs @@ -125,12 +125,17 @@ pub struct Manifest { // [impl->REQ-ADAPTER-FLOOR-ENFORCE] pub fn version_meets_floor(core: &str, floor: &str) -> bool { let parts = |s: &str| -> Vec { - s.split('.').map(|c| c.trim().parse::().unwrap_or(0)).collect() + s.split('.') + .map(|c| c.trim().parse::().unwrap_or(0)) + .collect() }; let (c, f) = (parts(core), parts(floor)); let n = c.len().max(f.len()); for i in 0..n { - let (cv, fv) = (c.get(i).copied().unwrap_or(0), f.get(i).copied().unwrap_or(0)); + let (cv, fv) = ( + c.get(i).copied().unwrap_or(0), + f.get(i).copied().unwrap_or(0), + ); if cv != fv { return cv > fv; // core > floor at the first differing component ⇒ satisfied } @@ -1371,7 +1376,11 @@ impl Manifest { // Dead config: warn on an unfillable key, refuse nothing. let dead: Vec = crate::runtime::placeholder_keys(&role.command) .into_iter() - .chain(role.cwd.iter().flat_map(|c| crate::runtime::placeholder_keys(c))) + .chain( + role.cwd + .iter() + .flat_map(|c| crate::runtime::placeholder_keys(c)), + ) .chain(role.keys.iter().cloned()) .filter(|k| !crate::runtime::is_fillable_key_for_role(role_name, k)) .collect(); @@ -1462,8 +1471,8 @@ const RETIRED_UNSPAWNED_ROLES: &[&str] = &["psyche_init"]; #[cfg(test)] mod tests { - use std::time::Duration; use super::*; + use std::time::Duration; /// A full harness manifest exercising every section (the worked /// `claude-spt` example from MANIFEST.md, trimmed to the parsed surface). @@ -1574,7 +1583,10 @@ types = ["image", "sound", "event"] assert_eq!(m.env["OWL_SESSION_ID"].direction, EnvDirection::Inject); // digest: the extractor seam with own source + presentation defaults let dig = m.digest.as_ref().unwrap(); - assert_eq!(dig.extractor, "claude-spt-digest --session {session_id} --in {source}"); + assert_eq!( + dig.extractor, + "claude-spt-digest --session {session_id} --in {source}" + ); assert_eq!(dig.window_turns, Some(5)); assert_eq!(dig.arg_truncation, Some(40)); assert_eq!(dig.sprint_collapse, Some(true)); @@ -1638,8 +1650,14 @@ types = ["image", "sound", "event"] let u = m.update.clone().unwrap(); assert_eq!(u.avenue, UpdateAvenue::GhRelease); assert_eq!(u.repo.as_deref(), Some("user/repo")); - assert!(u.asset.is_none(), "asset is optional (defaults to adapter.spt)"); - assert!(u.signing_key.is_none(), "signing_key is optional for gh_release"); + assert!( + u.asset.is_none(), + "asset is optional (defaults to adapter.spt)" + ); + assert!( + u.signing_key.is_none(), + "signing_key is optional for gh_release" + ); let reparsed = Manifest::from_toml_str(&m.to_toml_string().unwrap()).unwrap(); assert_eq!(m.update, reparsed.update, "gh_release round-trips"); @@ -1708,7 +1726,8 @@ types = ["image", "sound", "event"] // tunnel's opaque wire). #[test] fn shell_tunnel_opt_in() { - let base = "[adapter]\nname=\"u\"\nkind=\"shell\"\nversion=\"1\"\nmin_spt_core_version=\"1\"\n\n\ + let base = + "[adapter]\nname=\"u\"\nkind=\"shell\"\nversion=\"1\"\nmin_spt_core_version=\"1\"\n\n\ [shell]\nspawn=\"usbip-shell --link {link_token}\"\n"; // enabled + labelled → parses, fields preserved, round-trips. @@ -1780,8 +1799,7 @@ types = ["image", "sound", "event"] .contains("message-idle-translation-binary")); // declared with an empty path → refused at validate. - let empty = - format!("{base}\n[message-idle-translation-binary]\npath = \"\"\n"); + let empty = format!("{base}\n[message-idle-translation-binary]\npath = \"\"\n"); let err = Manifest::from_toml_str(&empty).unwrap_err().to_string(); assert!( err.contains("message-idle-translation-binary") && err.contains("non-empty"), @@ -1815,7 +1833,9 @@ types = ["image", "sound", "event"] \n[shell]\nspawn = 'gw-shell'\n"; // start = "boot", grace unstated ⇒ the 30s default. - let boot = format!("{base}\n[service]\ncommand = '{{adapter_dir}}/gw-hub serve'\nstart = \"boot\"\n"); + let boot = format!( + "{base}\n[service]\ncommand = '{{adapter_dir}}/gw-hub serve'\nstart = \"boot\"\n" + ); let m = Manifest::from_toml_str(&boot).expect("[service] boot parses"); let svc = m.service.as_ref().expect("service present"); assert_eq!(svc.command, "{adapter_dir}/gw-hub serve"); @@ -1869,9 +1889,8 @@ types = ["image", "sound", "event"] "an empty command has nothing to spawn: {err}" ); - let zero = format!( - "{base}\n[service]\ncommand = 'gw-hub'\nstart = \"boot\"\nstop_grace_ms = 0\n" - ); + let zero = + format!("{base}\n[service]\ncommand = 'gw-hub'\nstart = \"boot\"\nstop_grace_ms = 0\n"); let err = Manifest::from_toml_str(&zero).unwrap_err().to_string(); assert!( err.contains("stop_grace_ms must be > 0"), @@ -1932,8 +1951,7 @@ types = ["image", "sound", "event"] ); // empty command → refused. - let empty = - format!("{base}\n[message-idle-translation-binary]\ncommand = \"\"\n"); + let empty = format!("{base}\n[message-idle-translation-binary]\ncommand = \"\"\n"); let err = Manifest::from_toml_str(&empty).unwrap_err().to_string(); assert!( err.contains("`command` must be non-empty"), @@ -1984,9 +2002,8 @@ types = ["image", "sound", "event"] ); // is_empty() is false when ONLY resume is declared (no self, no dirs). - let resume_only = format!( - "{base}\n[session.resume]\ncommand = 'claude -r {{session_id}}'\n" - ); + let resume_only = + format!("{base}\n[session.resume]\ncommand = 'claude -r {{session_id}}'\n"); let mr = Manifest::from_toml_str(&resume_only).expect("resume-only parses"); assert!( !mr.session.is_empty(), @@ -1997,7 +2014,10 @@ types = ["image", "sound", "event"] // Round-trip: parse → emit → reparse is stable for the resume role. let reparsed = Manifest::from_toml_str(&m.to_toml_string().unwrap()).unwrap(); - assert_eq!(m.session.resume, reparsed.session.resume, "resume round-trips"); + assert_eq!( + m.session.resume, reparsed.session.resume, + "resume round-trips" + ); let emitted = m.to_toml_string().unwrap(); assert!( emitted.contains("[session.resume]"), @@ -2006,9 +2026,8 @@ types = ["image", "sound", "event"] // BACK-COMPAT: a manifest with [session.self] but NO [session.resume] // parses with resume == None (an old adapter is unaffected). - let no_resume = format!( - "{base}\n[session.self]\ncommand = 'claude --session-id {{session_id}}'\n" - ); + let no_resume = + format!("{base}\n[session.self]\ncommand = 'claude --session-id {{session_id}}'\n"); let m0 = Manifest::from_toml_str(&no_resume).expect("no-resume parses"); assert!(m0.session.self_.is_some()); assert!( @@ -2153,7 +2172,10 @@ class_key = "hid" regex: false, }; // Case-insensitive substring; returns the matched keyword. - assert_eq!(literal.matched_keyword("how do i spt send a msg"), Some("SPT send")); + assert_eq!( + literal.matched_keyword("how do i spt send a msg"), + Some("SPT send") + ); assert_eq!(literal.matched_keyword("the OWL hoots"), Some("owl")); assert_eq!(literal.matched_keyword("nothing here"), None); @@ -2164,7 +2186,10 @@ class_key = "hid" regex: true, }; assert_eq!(re.matched_keyword("run spt send now"), Some(r"spt\s+\w+")); - assert!(re.matched_keyword("sptsend").is_none(), "regex needs the whitespace"); + assert!( + re.matched_keyword("sptsend").is_none(), + "regex needs the whitespace" + ); // An invalid regex matches nothing (best-effort, never panics). let bad = Hint { @@ -2188,7 +2213,11 @@ class_key = "hid" .expect("parses"); assert_eq!(parent.hints.len(), 1); let merged = crate::profile::resolve(&parent, "p").expect("resolves"); - assert_eq!(merged.hints.len(), 1, "array replaced wholesale, not spliced"); + assert_eq!( + merged.hints.len(), + 1, + "array replaced wholesale, not spliced" + ); assert_eq!(merged.hints[0].text, "profile hint"); } @@ -2340,7 +2369,10 @@ extractor = "extract" "#; let e = Manifest::from_toml_str(no_src).unwrap_err(); assert!(matches!(e, ManifestError::Validation(_))); - assert!(e.to_string().contains("source") || e.to_string().contains("locate_template"), "{e}"); + assert!( + e.to_string().contains("source") || e.to_string().contains("locate_template"), + "{e}" + ); // Zero window. let zero = r#" @@ -2483,14 +2515,26 @@ window_turns = 0 #[test] fn version_meets_floor_numeric_not_lexical() { // Equal boundary ⇒ satisfied (floor is at-LEAST, not strictly-newer). - assert!(version_meets_floor("0.25.0", "0.25.0"), "equal meets the floor"); + assert!( + version_meets_floor("0.25.0", "0.25.0"), + "equal meets the floor" + ); // Core strictly above the floor ⇒ satisfied. - assert!(version_meets_floor("0.26.0", "0.25.0"), "core > floor passes"); - assert!(version_meets_floor("1.0.0", "0.9.9"), "major bump clears any minor"); + assert!( + version_meets_floor("0.26.0", "0.25.0"), + "core > floor passes" + ); + assert!( + version_meets_floor("1.0.0", "0.9.9"), + "major bump clears any minor" + ); // Core below the floor ⇒ refused. - assert!(!version_meets_floor("0.24.9", "0.25.0"), "core < floor refused"); + assert!( + !version_meets_floor("0.24.9", "0.25.0"), + "core < floor refused" + ); // The 0.9 < 0.25 trap: a LEXICAL compare says "0.9.0" > "0.25.0" (because '9' > // '2'), which would wrongly PASS a 0.25.0 floor on a 0.9.0 core. Numeric compare @@ -2505,8 +2549,14 @@ window_turns = 0 ); // Zero-pad equivalence: a shorter version is right-padded with zeros. - assert!(version_meets_floor("1.0", "1.0.0"), "1.0 == 1.0.0 after zero-pad"); - assert!(version_meets_floor("1.0.0", "1.0"), "and the reverse padding"); + assert!( + version_meets_floor("1.0", "1.0.0"), + "1.0 == 1.0.0 after zero-pad" + ); + assert!( + version_meets_floor("1.0.0", "1.0"), + "and the reverse padding" + ); // The perri repro: a fresh floor bump refuses the older shipped core. assert!( @@ -2557,11 +2607,17 @@ window_turns = 0 #[test] fn role_template_is_role_aware_for_notif_extras() { let ok = role_manifest("[session.notif]\ncommand = 'toast {notif_id} {notif_body} {id}'\n"); - assert!(ok.validate_role_templates().is_ok(), "notif extras + base keys fill"); + assert!( + ok.validate_role_templates().is_ok(), + "notif extras + base keys fill" + ); let bad = role_manifest("[session.self]\ncommand = 'run {notif_body}'\n"); let msg = bad.validate_role_templates().unwrap_err().to_string(); - assert!(msg.contains("notif_body"), "a notif-only key is unfillable outside notif: {msg}"); + assert!( + msg.contains("notif_body"), + "a notif-only key is unfillable outside notif: {msg}" + ); } // [unit->REQ-ADAPTER-TEMPLATE-KEY-VALIDATION] a var declared in BOTH a spawned @@ -2614,7 +2670,10 @@ window_turns = 0 [session.self]\ncommand = 'run'\n", ); let msg = bad.validate_role_templates().unwrap_err().to_string(); - assert!(msg.contains("gone_key"), "an [env] inject value's dead key refuses: {msg}"); + assert!( + msg.contains("gone_key"), + "an [env] inject value's dead key refuses: {msg}" + ); } // [unit->REQ-PSYCHE-INVOCATION-BUDGET-PER-ROLE] the budget resolution: default @@ -2739,7 +2798,8 @@ min_spt_core_version=\"0\" assert!(!m(" [io] compliance = false -").shortform_enabled()); +") + .shortform_enabled()); } // [unit->REQ-IO-SHORTFORM-GATE] the declaration turns it on, which is the @@ -2749,7 +2809,8 @@ compliance = false assert!(m(" [io] compliance = true -").shortform_enabled()); +") + .shortform_enabled()); } // [unit->REQ-IO-SHORTFORM-GATE] ruling 8's opt-out: an exotic harness can @@ -2762,11 +2823,13 @@ compliance = true [io] compliance = true shortform = false -").shortform_enabled()); +") + .shortform_enabled()); assert!(m(" [io] compliance = true shortform = true -").shortform_enabled()); +") + .shortform_enabled()); } } diff --git a/crates/spt-runtime/src/profile.rs b/crates/spt-runtime/src/profile.rs index dfcb6a28..a36aaea0 100644 --- a/crates/spt-runtime/src/profile.rs +++ b/crates/spt-runtime/src/profile.rs @@ -289,7 +289,8 @@ mod tests { // [unit->REQ-MANIFEST-2] #[test] fn deep_nested_leaf_replace() { - let base = v("[shell.capabilities.run]\nargs = [\"cmd\"]\n[shell]\nrequire_approval = \"none\""); + let base = + v("[shell.capabilities.run]\nargs = [\"cmd\"]\n[shell]\nrequire_approval = \"none\""); let overlay = v("[shell]\nrequire_approval = \"always\""); let merged = merge_leaf_replace(&base, &overlay); // The capabilities sub-table is untouched; only require_approval flips. @@ -333,9 +334,19 @@ over_cap = "approve" let parent = Manifest::from_toml_str(PROFILED_SHELL).expect("parent parses"); let merged = resolve(&parent, "work").expect("work resolves"); let shell = merged.shell.expect("merged has shell"); - assert_eq!(shell.require_approval, ShellApproval::Always, "floor tightened"); - assert_eq!(shell.spawn, "run --thing", "untouched leaf survives the merge"); - assert!(merged.profiles.is_empty(), "resolved view drops the profile catalogue"); + assert_eq!( + shell.require_approval, + ShellApproval::Always, + "floor tightened" + ); + assert_eq!( + shell.spawn, "run --thing", + "untouched leaf survives the merge" + ); + assert!( + merged.profiles.is_empty(), + "resolved view drops the profile catalogue" + ); } /// An undeclared profile name is a distinct, typed error. @@ -354,7 +365,10 @@ over_cap = "approve" #[test] fn tighten_only_allows_tightening() { let parent = Manifest::from_toml_str(PROFILED_SHELL).expect("parent parses"); - assert!(resolve(&parent, "work").is_ok(), "remembered -> always is a tighten"); + assert!( + resolve(&parent, "work").is_ok(), + "remembered -> always is a tighten" + ); } /// Tighten-only: a profile that *lowers* the approval floor is refused at @@ -388,13 +402,14 @@ over_cap = "approve" // [unit->REQ-MANIFEST-3] #[test] fn string_dot_path_read_write() { - let mut t: toml::Table = toml::from_str( - "greeting = \"hi\"\n[hook]\nadditionalContext = \"ctx\"\n", - ) - .unwrap(); + let mut t: toml::Table = + toml::from_str("greeting = \"hi\"\n[hook]\nadditionalContext = \"ctx\"\n").unwrap(); // Read: top-level leaf, nested leaf, and a miss. - assert_eq!(string_at(&t, "greeting").and_then(|v| v.as_str()), Some("hi")); + assert_eq!( + string_at(&t, "greeting").and_then(|v| v.as_str()), + Some("hi") + ); assert_eq!( string_at(&t, "hook.additionalContext").and_then(|v| v.as_str()), Some("ctx") @@ -407,8 +422,14 @@ over_cap = "approve" // Write: overwrite a leaf, and create an intermediate table. set_string_at(&mut t, "greeting", Value::String("yo".into())).unwrap(); set_string_at(&mut t, "deep.nest.key", Value::String("v".into())).unwrap(); - assert_eq!(string_at(&t, "greeting").and_then(|v| v.as_str()), Some("yo")); - assert_eq!(string_at(&t, "deep.nest.key").and_then(|v| v.as_str()), Some("v")); + assert_eq!( + string_at(&t, "greeting").and_then(|v| v.as_str()), + Some("yo") + ); + assert_eq!( + string_at(&t, "deep.nest.key").and_then(|v| v.as_str()), + Some("v") + ); // Writing through an existing non-table leaf errs (no clobber). assert!(set_string_at(&mut t, "greeting.x", Value::String("z".into())).is_err()); // An empty segment errs. @@ -453,8 +474,14 @@ over_cap = "approve" ) .expect("parses"); let merged = resolve(&parent, "p").expect("resolves"); - assert_eq!(merged.strings.get("kept").and_then(|v| v.as_str()), Some("base")); - assert_eq!(merged.strings.get("flip").and_then(|v| v.as_str()), Some("profile")); + assert_eq!( + merged.strings.get("kept").and_then(|v| v.as_str()), + Some("base") + ); + assert_eq!( + merged.strings.get("flip").and_then(|v| v.as_str()), + Some("profile") + ); } /// Composite addressing splits on the first `:`; a bare name has no profile. @@ -462,7 +489,10 @@ over_cap = "approve" #[test] fn split_option_first_colon() { assert_eq!(split_option("claude-spt"), ("claude-spt", None)); - assert_eq!(split_option("claude-spt:work"), ("claude-spt", Some("work"))); + assert_eq!( + split_option("claude-spt:work"), + ("claude-spt", Some("work")) + ); // A profile name may contain '-'; the split is on the first ':' only. assert_eq!( split_option("spt-usbip-driver:hid-only"), diff --git a/crates/spt-runtime/src/registry.rs b/crates/spt-runtime/src/registry.rs index 352bf89d..9a6dd89b 100644 --- a/crates/spt-runtime/src/registry.rs +++ b/crates/spt-runtime/src/registry.rs @@ -98,7 +98,11 @@ pub enum RegistryError { /// verbs (add + update) BEFORE anything is installed or the registry is written. /// The `Display` is the F-1 operator refusal (names the installed core, the /// floor, and the next action) — the ONE message shape both verbs surface. - CoreFloor { adapter: String, core: String, floor: String }, + CoreFloor { + adapter: String, + core: String, + floor: String, + }, } impl std::fmt::Display for RegistryError { @@ -109,14 +113,23 @@ impl std::fmt::Display for RegistryError { RegistryError::NotRegistered(n) => write!(f, "adapter not registered: {n}"), RegistryError::BadRecord(n) => write!(f, "corrupt adapter record: {n}"), RegistryError::InvalidProfileName(n) => { - write!(f, "invalid profile name '{n}' (no ':', path separators, or whitespace)") + write!( + f, + "invalid profile name '{n}' (no ':', path separators, or whitespace)" + ) } RegistryError::ProfileShadowsShipped(n) => { - write!(f, "local profile '{n}' would shadow a shipped profile of the same name") + write!( + f, + "local profile '{n}' would shadow a shipped profile of the same name" + ) } RegistryError::ProfileNotFound(n) => write!(f, "local profile not found: {n}"), RegistryError::ShippedProfileImmutable(n) => { - write!(f, "profile '{n}' is shipped (adapter-owned); only local profiles are editable") + write!( + f, + "profile '{n}' is shipped (adapter-owned); only local profiles are editable" + ) } RegistryError::BadStringPointer(m) => { write!(f, "invalid [strings] file pointer: {m}") @@ -128,7 +141,11 @@ impl std::fmt::Display for RegistryError { extracted/downloaded. Complete the install (e.g. re-run the installer or \ `spt adapter add`) so the source tree exists, then retry." ), - RegistryError::CoreFloor { adapter, core, floor } => write!( + RegistryError::CoreFloor { + adapter, + core, + floor, + } => write!( f, "adapter '{adapter}' requires spt-core {floor} or newer, but this machine \ runs spt-core {core}. Update spt-core first (`spt update`), then retry." @@ -400,8 +417,11 @@ pub fn register_with_core( // post-copy and survive the source going away (adapter updates overwrite // this — REQ-MANIFEST-5). Pointer mode reads strings/ live from source. if src_strings_dir.is_dir() { - copy_dir_all(&src_strings_dir, &shipped_strings_dir(adapters_dir, &record)) - .map_err(RegistryError::Io)?; + copy_dir_all( + &src_strings_dir, + &shipped_strings_dir(adapters_dir, &record), + ) + .map_err(RegistryError::Io)?; } } save_record(adapters_dir, &record)?; @@ -605,7 +625,10 @@ pub fn create_local_profile( profile::resolve_overlay(&parent, &overlay).map_err(RegistryError::Manifest)?; let dir = local_profiles_dir(adapters_dir, adapter); std::fs::create_dir_all(&dir)?; - atomic_write_string(&local_profile_file(adapters_dir, adapter, profile), overlay_toml)?; + atomic_write_string( + &local_profile_file(adapters_dir, adapter, profile), + overlay_toml, + )?; Ok(()) } @@ -654,7 +677,11 @@ pub fn get_string( // the file's contents (REQ-MANIFEST-5), lazily — so live edits reflect. let Some(rel) = profile::as_file_pointer(value) else { // [impl->REQ-MANIFEST-SUBST] lazy adapter-static substitution at read time. - return Ok(Some(subst_string_value(value.clone(), &record, node.as_deref()))); + return Ok(Some(subst_string_value( + value.clone(), + &record, + node.as_deref(), + ))); }; // Provenance (the update-safety guard): if this key is supplied as a file // pointer by a LOCAL profile, resolve against its user-owned dir (survives @@ -688,7 +715,9 @@ fn subst_string_value(value: Value, record: &AdapterRecord, node: Option<&str>) node, )), Value::Array(arr) => Value::Array( - arr.into_iter().map(|v| subst_string_value(v, record, node)).collect(), + arr.into_iter() + .map(|v| subst_string_value(v, record, node)) + .collect(), ), Value::Table(tbl) => Value::Table( tbl.into_iter() @@ -748,13 +777,14 @@ pub fn set_local_string( let strings = overlay_table .entry("strings".to_string()) .or_insert_with(|| Value::Table(toml::Table::new())); - let strings_table = strings - .as_table_mut() - .ok_or_else(|| RegistryError::BadRecord(format!("profiles/{profile}: [strings] not a table")))?; + let strings_table = strings.as_table_mut().ok_or_else(|| { + RegistryError::BadRecord(format!("profiles/{profile}: [strings] not a table")) + })?; profile::set_string_at(strings_table, key_path, Value::String(value.to_string())) .map_err(RegistryError::Manifest)?; - let overlay_toml = toml::to_string_pretty(&overlay) - .map_err(|e| RegistryError::Manifest(crate::manifest::ManifestError::Validation(e.to_string())))?; + let overlay_toml = toml::to_string_pretty(&overlay).map_err(|e| { + RegistryError::Manifest(crate::manifest::ManifestError::Validation(e.to_string())) + })?; // Re-validate + write atomically through the create-time guards. create_local_profile(adapters_dir, adapter, profile, &overlay_toml) } @@ -1010,7 +1040,11 @@ hostable_types = ["LiveAgent"] let err = register_with_core(&adapters, &src, 1000, "0.25.0") .expect_err("a below-floor core must be refused"); match err { - RegistryError::CoreFloor { adapter, core, floor } => { + RegistryError::CoreFloor { + adapter, + core, + floor, + } => { assert_eq!(adapter, "highfloor"); assert_eq!(core, "0.25.0"); assert_eq!(floor, "9.9.9"); @@ -1147,7 +1181,9 @@ hostable_types = ["LiveAgent"] // registered() skips it (not in the active set), never panics/crashes. assert!( - registered(&adapters).iter().all(|(r, _)| r.name != rec.name), + registered(&adapters) + .iter() + .all(|(r, _)| r.name != rec.name), "a deferred-manifest adapter is skipped from the active set, not crashed" ); } @@ -1178,11 +1214,20 @@ hostable_types = ["LiveAgent"] // Shipped profile. let (_, shipped) = resolve_option(&adapters, "mock-shell:locked").unwrap(); - assert_eq!(approval(&shipped), ShellApproval::Always, "shipped resolves"); + assert_eq!( + approval(&shipped), + ShellApproval::Always, + "shipped resolves" + ); // Local profile (tightens further-or-equal — always over remembered). - create_local_profile(&adapters, "mock-shell", "work", "[shell]\nrequire_approval = \"always\"\n") - .unwrap(); + create_local_profile( + &adapters, + "mock-shell", + "work", + "[shell]\nrequire_approval = \"always\"\n", + ) + .unwrap(); let (_, local) = resolve_option(&adapters, "mock-shell:work").unwrap(); assert_eq!(approval(&local), ShellApproval::Always, "local resolves"); assert_eq!(local_profile_names(&adapters, "mock-shell"), vec!["work"]); @@ -1197,14 +1242,23 @@ hostable_types = ["LiveAgent"] use crate::manifest::ShellApproval; let tmp = tempfile::tempdir().unwrap(); let adapters = registered_shell(tmp.path()); - create_local_profile(&adapters, "mock-shell", "work", "[shell]\nrequire_approval = \"always\"\n") - .unwrap(); + create_local_profile( + &adapters, + "mock-shell", + "work", + "[shell]\nrequire_approval = \"always\"\n", + ) + .unwrap(); let set = registered(&adapters); let bare = resolve_option_in(&set, &adapters, "mock-shell").unwrap(); assert_eq!(approval(&bare), ShellApproval::Remembered, "bare = parent"); let shipped = resolve_option_in(&set, &adapters, "mock-shell:locked").unwrap(); - assert_eq!(approval(&shipped), ShellApproval::Always, "shipped overlays"); + assert_eq!( + approval(&shipped), + ShellApproval::Always, + "shipped overlays" + ); let local = resolve_option_in(&set, &adapters, "mock-shell:work").unwrap(); assert_eq!(approval(&local), ShellApproval::Always, "local overlays"); @@ -1220,8 +1274,13 @@ hostable_types = ["LiveAgent"] fn local_profile_survives_readd() { let tmp = tempfile::tempdir().unwrap(); let adapters = registered_shell(tmp.path()); - create_local_profile(&adapters, "mock-shell", "work", "[shell]\nrequire_approval = \"always\"\n") - .unwrap(); + create_local_profile( + &adapters, + "mock-shell", + "work", + "[shell]\nrequire_approval = \"always\"\n", + ) + .unwrap(); // Re-register the adapter (adapter update / re-add). let src = seed_source(tmp.path(), "ms-src2", SHELL_COPY_PROFILED); @@ -1248,13 +1307,23 @@ hostable_types = ["LiveAgent"] // Loosen the consent floor (remembered -> none). assert!(matches!( - create_local_profile(&adapters, "mock-shell", "loose", "[shell]\nrequire_approval = \"none\"\n"), + create_local_profile( + &adapters, + "mock-shell", + "loose", + "[shell]\nrequire_approval = \"none\"\n" + ), Err(RegistryError::Manifest(_)) )); // Invalid name (contains the address separator). assert!(matches!( - create_local_profile(&adapters, "mock-shell", "a:b", "[shell]\nrequire_approval = \"always\"\n"), + create_local_profile( + &adapters, + "mock-shell", + "a:b", + "[shell]\nrequire_approval = \"always\"\n" + ), Err(RegistryError::InvalidProfileName(_)) )); @@ -1270,8 +1339,13 @@ hostable_types = ["LiveAgent"] fn delete_local_profile_rules() { let tmp = tempfile::tempdir().unwrap(); let adapters = registered_shell(tmp.path()); - create_local_profile(&adapters, "mock-shell", "work", "[shell]\nrequire_approval = \"always\"\n") - .unwrap(); + create_local_profile( + &adapters, + "mock-shell", + "work", + "[shell]\nrequire_approval = \"always\"\n", + ) + .unwrap(); assert!(matches!( delete_local_profile(&adapters, "mock-shell", "locked"), @@ -1305,10 +1379,14 @@ hostable_types = ["LiveAgent"] // Bare option reads the base string; a missing key is None. assert_eq!( - get_string(&adapters, "mock-shell", "base").unwrap().and_then(|v| v.as_str().map(str::to_string)), + get_string(&adapters, "mock-shell", "base") + .unwrap() + .and_then(|v| v.as_str().map(str::to_string)), Some("parent".to_string()) ); - assert!(get_string(&adapters, "mock-shell", "absent").unwrap().is_none()); + assert!(get_string(&adapters, "mock-shell", "absent") + .unwrap() + .is_none()); // set-string requires a LOCAL profile to exist first. create_local_profile(&adapters, "mock-shell", "work", "").unwrap(); @@ -1316,15 +1394,21 @@ hostable_types = ["LiveAgent"] set_local_string(&adapters, "mock-shell", "work", "hook.ctx", "deep").unwrap(); // The composite reads the overlaid value; the bare option is unchanged. assert_eq!( - get_string(&adapters, "mock-shell:work", "base").unwrap().and_then(|v| v.as_str().map(str::to_string)), + get_string(&adapters, "mock-shell:work", "base") + .unwrap() + .and_then(|v| v.as_str().map(str::to_string)), Some("overridden".to_string()) ); assert_eq!( - get_string(&adapters, "mock-shell:work", "hook.ctx").unwrap().and_then(|v| v.as_str().map(str::to_string)), + get_string(&adapters, "mock-shell:work", "hook.ctx") + .unwrap() + .and_then(|v| v.as_str().map(str::to_string)), Some("deep".to_string()) ); assert_eq!( - get_string(&adapters, "mock-shell", "base").unwrap().and_then(|v| v.as_str().map(str::to_string)), + get_string(&adapters, "mock-shell", "base") + .unwrap() + .and_then(|v| v.as_str().map(str::to_string)), Some("parent".to_string()), "the bare parent is untouched" ); @@ -1353,8 +1437,10 @@ hostable_types = ["LiveAgent"] ); let src = seed_source(tmp, "cc-src", &toml_src); let strings_dir = src.join("strings"); - std::fs::create_dir_all(strings_dir.join(Path::new(file_rel).parent().unwrap_or(Path::new("")))) - .unwrap(); + std::fs::create_dir_all( + strings_dir.join(Path::new(file_rel).parent().unwrap_or(Path::new(""))), + ) + .unwrap(); std::fs::write(strings_dir.join(file_rel), body).unwrap(); let adapters = tmp.join("adapters"); register(&adapters, &src, 1000).unwrap(); @@ -1371,20 +1457,29 @@ hostable_types = ["LiveAgent"] // Pointer → file contents; the inline literal still reads as itself. assert_eq!( - get_string(&adapters, "mock-cc", "body").unwrap().and_then(|v| v.as_str().map(str::to_string)), + get_string(&adapters, "mock-cc", "body") + .unwrap() + .and_then(|v| v.as_str().map(str::to_string)), Some("SKILL BODY".to_string()) ); assert_eq!( - get_string(&adapters, "mock-cc", "inline").unwrap().and_then(|v| v.as_str().map(str::to_string)), + get_string(&adapters, "mock-cc", "inline") + .unwrap() + .and_then(|v| v.as_str().map(str::to_string)), Some("literal".to_string()) ); // Lazy: edit the (copied) file; get-string reflects it without re-register. let copied = adapters.join("mock-cc").join("strings").join("skill.md"); - assert!(copied.exists(), "shipped strings/ copied into the held copy"); + assert!( + copied.exists(), + "shipped strings/ copied into the held copy" + ); std::fs::write(&copied, "EDITED BODY").unwrap(); assert_eq!( - get_string(&adapters, "mock-cc", "body").unwrap().and_then(|v| v.as_str().map(str::to_string)), + get_string(&adapters, "mock-cc", "body") + .unwrap() + .and_then(|v| v.as_str().map(str::to_string)), Some("EDITED BODY".to_string()), "lazy read reflects the live file edit" ); @@ -1410,10 +1505,17 @@ hostable_types = ["LiveAgent"] register(&adapters, &traverse, 1), Err(RegistryError::BadStringPointer(_)) )); - assert!(!adapters.join("esc1").exists(), "escaping pointer records nothing"); + assert!( + !adapters.join("esc1").exists(), + "escaping pointer records nothing" + ); // Absolute path. - let abs_path = if cfg!(windows) { "C:\\\\windows\\\\system32\\\\x" } else { "/etc/passwd" }; + let abs_path = if cfg!(windows) { + "C:\\\\windows\\\\system32\\\\x" + } else { + "/etc/passwd" + }; let absolute = seed_source( tmp.path(), "esc2", @@ -1427,7 +1529,10 @@ hostable_types = ["LiveAgent"] register(&adapters, &absolute, 2), Err(RegistryError::BadStringPointer(_)) )); - assert!(!adapters.join("esc2").exists(), "absolute pointer records nothing"); + assert!( + !adapters.join("esc2").exists(), + "absolute pointer records nothing" + ); } // [unit->REQ-MANIFEST-5] a missing-at-READ file (deleted after a valid @@ -1456,12 +1561,16 @@ hostable_types = ["LiveAgent"] set_local_string(&adapters, "mock-cc", "work", "body", "LOCAL OVERRIDE").unwrap(); assert_eq!( - get_string(&adapters, "mock-cc:work", "body").unwrap().and_then(|v| v.as_str().map(str::to_string)), + get_string(&adapters, "mock-cc:work", "body") + .unwrap() + .and_then(|v| v.as_str().map(str::to_string)), Some("LOCAL OVERRIDE".to_string()), "local literal leaf-replaces the shipped pointer" ); assert_eq!( - get_string(&adapters, "mock-cc", "body").unwrap().and_then(|v| v.as_str().map(str::to_string)), + get_string(&adapters, "mock-cc", "body") + .unwrap() + .and_then(|v| v.as_str().map(str::to_string)), Some("SHIPPED BODY".to_string()), "the bare parent still resolves the shipped file" ); @@ -1489,8 +1598,13 @@ hostable_types = ["LiveAgent"] "an : fallback target resolves" ); // A local profile target too. - create_local_profile(&adapters, "mock-shell", "work", "[shell]\nrequire_approval = \"always\"\n") - .unwrap(); + create_local_profile( + &adapters, + "mock-shell", + "work", + "[shell]\nrequire_approval = \"always\"\n", + ) + .unwrap(); assert!( resolve_option(&adapters, "mock-shell:work").is_ok(), "an : fallback target resolves" diff --git a/crates/spt-runtime/src/resolve.rs b/crates/spt-runtime/src/resolve.rs index 02742106..c113b4e6 100644 --- a/crates/spt-runtime/src/resolve.rs +++ b/crates/spt-runtime/src/resolve.rs @@ -176,12 +176,11 @@ pub fn set_active(adapters_dir: &Path, option: &str) -> Result, SetE pub fn clear_active(adapters_dir: &Path, target: &str) -> Vec { let mut ap = load(adapters_dir); let key = normalize_basename(target); - let removed: Vec = ap - .0 - .iter() - .filter(|(k, v)| **k == key || crate::profile::split_option(v).0 == target) - .map(|(k, _)| k.clone()) - .collect(); + let removed: Vec = + ap.0.iter() + .filter(|(k, v)| **k == key || crate::profile::split_option(v).0 == target) + .map(|(k, _)| k.clone()) + .collect(); for k in &removed { ap.0.remove(k); } @@ -196,12 +195,11 @@ pub fn clear_active(adapters_dir: &Path, target: &str) -> Vec { /// Returns the removed keys. (A thin alias for [`clear_active`] by adapter name.) pub fn prune_adapter(adapters_dir: &Path, adapter: &str) -> Vec { let mut ap = load(adapters_dir); - let removed: Vec = ap - .0 - .iter() - .filter(|(_, v)| crate::profile::split_option(v).0 == adapter) - .map(|(k, _)| k.clone()) - .collect(); + let removed: Vec = + ap.0.iter() + .filter(|(_, v)| crate::profile::split_option(v).0 == adapter) + .map(|(k, _)| k.clone()) + .collect(); for k in &removed { ap.0.remove(k); } @@ -413,7 +411,10 @@ mod tests { "[profiles.live]\n[profiles.live.adapter]\nhostable_types = [\"LiveAgent\"]\n", ); // Without a pointer, the freshest (newer-spt) would win. - assert_eq!(resolve_from_basename(&adapters, "claude").unwrap(), "newer-spt"); + assert_eq!( + resolve_from_basename(&adapters, "claude").unwrap(), + "newer-spt" + ); // Pin claude-spt:live; now it wins for the `claude` binary. let keys = set_active(&adapters, "claude-spt:live").unwrap(); @@ -432,7 +433,10 @@ mod tests { let adapters = register_harness(tmp.path(), "claude-spt", &["claude"], 1000, ""); register_harness(tmp.path(), "other-spt", &["claude"], 2000, ""); set_active(&adapters, "claude-spt").unwrap(); - assert_eq!(resolve_from_basename(&adapters, "claude").unwrap(), "claude-spt"); + assert_eq!( + resolve_from_basename(&adapters, "claude").unwrap(), + "claude-spt" + ); // Soft-deregister the pinned adapter; the pointer is now stale. registry::deregister(&adapters, "claude-spt").unwrap(); @@ -449,7 +453,13 @@ mod tests { #[test] fn set_clear_prune_rules() { let tmp = tempfile::tempdir().unwrap(); - let adapters = register_harness(tmp.path(), "claude-spt", &["claude", "claude-cli"], 1000, ""); + let adapters = register_harness( + tmp.path(), + "claude-spt", + &["claude", "claude-cli"], + 1000, + "", + ); let keys = set_active(&adapters, "claude-spt").unwrap(); assert_eq!(keys, vec!["claude".to_string(), "claude-cli".to_string()]); @@ -467,7 +477,10 @@ mod tests { assert_eq!(load(&adapters).0.len(), 1, "the other binding remains"); // Prune by adapter drops what is left. - assert_eq!(prune_adapter(&adapters, "claude-spt"), vec!["claude-cli".to_string()]); + assert_eq!( + prune_adapter(&adapters, "claude-spt"), + vec!["claude-cli".to_string()] + ); assert!(load(&adapters).0.is_empty()); // An adapter with no host_binaries cannot be set active. @@ -520,8 +533,14 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); let adapters = register_harness(tmp.path(), "claude-spt", &["claude"], 1000, ""); set_active(&adapters, "claude-spt").unwrap(); - assert_eq!(pointer_file(&adapters), adapters.join("active-profiles.toml")); + assert_eq!( + pointer_file(&adapters), + adapters.join("active-profiles.toml") + ); assert!(pointer_file(&adapters).exists()); - assert!(adapters.join("claude-spt").is_dir(), "adapter dir is a sibling"); + assert!( + adapters.join("claude-spt").is_dir(), + "adapter dir is a sibling" + ); } } diff --git a/crates/spt-runtime/src/runtime.rs b/crates/spt-runtime/src/runtime.rs index f85212d7..0f896b8a 100644 --- a/crates/spt-runtime/src/runtime.rs +++ b/crates/spt-runtime/src/runtime.rs @@ -59,7 +59,8 @@ pub const IDENTITY_ENV_VARS: [&str; 3] = ["SPT_ENDPOINT_ID", "OWL_SESSION_ID", " // [impl->REQ-LIVE-AGENT-NO-INJECT-DELIVERY] F-033 leg (b) closure: the operator's // typed-unsubmitted garbage was this echo-verify re-drive, force-armed host-wide by // ambient env — this scrub is the fix (the raw payload+CR path was proven dead). -pub const INJECT_ECHO_ENV_VARS: [&str; 2] = ["SPT_INJECT_VERIFY_ECHO", "SPT_INJECT_FORCE_ECHO_MISS"]; +pub const INJECT_ECHO_ENV_VARS: [&str; 2] = + ["SPT_INJECT_VERIFY_ECHO", "SPT_INJECT_FORCE_ECHO_MISS"]; /// TEST-RIG TIMING knobs that must never arm from AMBIENT env — the same /// inheritance class as [`INJECT_ECHO_ENV_VARS`], third payload. These widen a @@ -429,10 +430,7 @@ pub fn inject_read_env_keys( if var.direction != EnvDirection::Read { continue; } - let resolved = captured - .get(name) - .cloned() - .or_else(|| var.value.clone()); + let resolved = captured.get(name).cloned().or_else(|| var.value.clone()); if let Some(value) = resolved { keys.entry(name.clone()) .or_insert_with(|| expand_tilde(&value)); @@ -451,7 +449,9 @@ pub fn expand_tilde(value: &str) -> String { let rest = if value == "~" { Some("") } else { - value.strip_prefix("~/").or_else(|| value.strip_prefix("~\\")) + value + .strip_prefix("~/") + .or_else(|| value.strip_prefix("~\\")) }; let Some(rest) = rest else { return value.to_string(); @@ -739,10 +739,7 @@ impl ManifestRuntime { /// psyche in the parent's captured account root, not the default. A stamped var /// overrides the ambient value. No-op when the map is empty. // [impl->REQ-PSYCHE-SPAWN-ENV-PARITY] - pub fn with_spawn_env( - mut self, - spawn_env: std::collections::BTreeMap, - ) -> Self { + pub fn with_spawn_env(mut self, spawn_env: std::collections::BTreeMap) -> Self { self.spawn_env = spawn_env; self } @@ -1275,7 +1272,8 @@ mod tests { .command_for(rt.role("echo_commune").unwrap(), &BTreeMap::new()) .unwrap(); assert_eq!( - cmd.get_current_dir().map(|p| p.to_string_lossy().replace('\\', "/")), + cmd.get_current_dir() + .map(|p| p.to_string_lossy().replace('\\', "/")), Some(role_dir_toml), "an adapter-declared role cwd always wins over the caller default" ); @@ -1349,7 +1347,8 @@ mod tests { .command_for(rt.role("echo_commune").unwrap(), &BTreeMap::new()) .unwrap(); assert_eq!( - cmd.get_current_dir().map(|p| p.to_string_lossy().replace('\\', "/")), + cmd.get_current_dir() + .map(|p| p.to_string_lossy().replace('\\', "/")), Some(role_dir_toml), "an ordinary endpoint keeps its adapter-declared role cwd" ); @@ -1399,7 +1398,10 @@ mod tests { // Stamp it → the captured value is threaded onto the spawn. let mut stamps = BTreeMap::new(); - stamps.insert("CLAUDE_CONFIG_DIR".to_string(), "/relocated/root".to_string()); + stamps.insert( + "CLAUDE_CONFIG_DIR".to_string(), + "/relocated/root".to_string(), + ); let rt = ManifestRuntime::new(m).with_spawn_env(stamps); let role = rt.role("psyche_resume").unwrap(); let cmd = rt.command_for(role, &BTreeMap::new()).unwrap(); @@ -1419,7 +1421,10 @@ mod tests { fn stamp_survives_env_remove() { let m = psyche_manifest("env_remove = [\"CLAUDE_CONFIG_DIR\"]\n"); let mut stamps = BTreeMap::new(); - stamps.insert("CLAUDE_CONFIG_DIR".to_string(), "/relocated/root".to_string()); + stamps.insert( + "CLAUDE_CONFIG_DIR".to_string(), + "/relocated/root".to_string(), + ); let rt = ManifestRuntime::new(m).with_spawn_env(stamps); let role = rt.role("psyche_resume").unwrap(); let cmd = rt.command_for(role, &BTreeMap::new()).unwrap(); @@ -1509,7 +1514,11 @@ mod tests { fn expand_tilde_expands_leading_home_only() { assert_eq!(expand_tilde("/abs/path"), "/abs/path"); assert_eq!(expand_tilde("plain"), "plain"); - assert_eq!(expand_tilde("a/~/b"), "a/~/b", "a mid-path ~ is not expanded"); + assert_eq!( + expand_tilde("a/~/b"), + "a/~/b", + "a mid-path ~ is not expanded" + ); let home = if cfg!(windows) { std::env::var("USERPROFILE") } else { @@ -1553,12 +1562,20 @@ mod tests { let q = keys(&[("psyche_prompt", r#"a "quoted" b"#)]); let argv_q = fill_template_tokens("runner --prompt {psyche_prompt}", &q).unwrap(); assert_eq!(argv_q, vec!["runner", "--prompt", r#"a "quoted" b"#]); - assert_eq!(argv_q.len(), 3, "a value with a quote injects no extra token"); + assert_eq!( + argv_q.len(), + 3, + "a value with a quote injects no extra token" + ); let s = keys(&[("psyche_prompt", "a; rm -rf b")]); let argv_s = fill_template_tokens("runner --prompt {psyche_prompt}", &s).unwrap(); assert_eq!(argv_s, vec!["runner", "--prompt", "a; rm -rf b"]); - assert_eq!(argv_s.len(), 3, "a value with a semicolon injects no extra token"); + assert_eq!( + argv_s.len(), + 3, + "a value with a semicolon injects no extra token" + ); } // [unit->REQ-MANIFEST-SUBST] the adapter-static substitution primitives @@ -1582,7 +1599,10 @@ mod tests { let mut k2 = BTreeMap::new(); inject_adapter_keys(&mut k2, None, Some("only-name")); assert!(!k2.contains_key("adapter_dir")); - assert_eq!(k2.get("adapter_name").map(String::as_str), Some("only-name")); + assert_eq!( + k2.get("adapter_name").map(String::as_str), + Some("only-name") + ); // subst: fills the adapter-static keys + node-static {node}, passes the // session-scoped placeholders through verbatim. @@ -1592,14 +1612,20 @@ mod tests { Some("claude-spt"), Some("HOSTX"), ); - assert_eq!(out, "/opt/cc/claude-spt hook {id} {session_id} claude-spt @HOSTX"); + assert_eq!( + out, + "/opt/cc/claude-spt hook {id} {session_id} claude-spt @HOSTX" + ); // an unavailable key (None source) passes through, never errors — {node} too. assert_eq!( subst_adapter_static("{adapter_dir}/x {node}", None, Some("n"), None), "{adapter_dir}/x {node}" ); // an unterminated brace passes through verbatim. - assert_eq!(subst_adapter_static("a{b", Some("d"), Some("n"), None), "a{b"); + assert_eq!( + subst_adapter_static("a{b", Some("d"), Some("n"), None), + "a{b" + ); // command_for resolves {adapter_dir} from the runtime's pinned dir + name. let m = Manifest::from_toml_str( diff --git a/crates/spt-store/src/access.rs b/crates/spt-store/src/access.rs index 6c38bc50..a5877a23 100644 --- a/crates/spt-store/src/access.rs +++ b/crates/spt-store/src/access.rs @@ -205,24 +205,74 @@ pub mod surface { // [impl->REQ-ACL-SURFACE-ATTRIBUTABILITY] // [impl->REQ-ACL-DISCOVER-DEFAULT-ON] pub const TABLE: &[Surface] = &[ - Surface { id: MSG, attributable: true, default_on: false, desc: "direct messages" }, - Surface { id: RC_VIEW, attributable: false, default_on: false, desc: "read-only terminal viewing" }, - Surface { id: RC_ATTACH, attributable: false, default_on: false, desc: "interactive terminal control" }, - Surface { id: DIGEST, attributable: false, default_on: false, desc: "cross-node digest pull" }, - Surface { id: WAKE, attributable: false, default_on: false, desc: "waking a resting endpoint" }, - Surface { id: SUSPEND, attributable: false, default_on: false, desc: "suspending a running endpoint" }, - Surface { id: XFER, attributable: false, default_on: false, desc: "file transfer" }, - Surface { id: SHELL_LINK, attributable: false, default_on: false, desc: "driving a linked shell" }, + Surface { + id: MSG, + attributable: true, + default_on: false, + desc: "direct messages", + }, + Surface { + id: RC_VIEW, + attributable: false, + default_on: false, + desc: "read-only terminal viewing", + }, + Surface { + id: RC_ATTACH, + attributable: false, + default_on: false, + desc: "interactive terminal control", + }, + Surface { + id: DIGEST, + attributable: false, + default_on: false, + desc: "cross-node digest pull", + }, + Surface { + id: WAKE, + attributable: false, + default_on: false, + desc: "waking a resting endpoint", + }, + Surface { + id: SUSPEND, + attributable: false, + default_on: false, + desc: "suspending a running endpoint", + }, + Surface { + id: XFER, + attributable: false, + default_on: false, + desc: "file transfer", + }, + Surface { + id: SHELL_LINK, + attributable: false, + default_on: false, + desc: "driving a linked shell", + }, // The one default-on row (releases#180). See [`Surface::default_on`] // for why the default is stated HERE and read in exactly one place. - Surface { id: DISCOVER, attributable: false, default_on: true, desc: "being found: resolve, advertise, and the resources blurb" }, + Surface { + id: DISCOVER, + attributable: false, + default_on: true, + desc: "being found: resolve, advertise, and the resources blurb", + }, // Non-attributable BY RULING this wave, not by accident: a fork request // carries no daemon-stamped session-proven sender, and making it the // second attributable family would change WHICH SUBJECT TIER may // express a fork grant — a second decision, in a wave scoped to one. // So node-tier subjects govern fork; the flip later is this one row. // [impl->REQ-FORK-ACCESS-GATED] - Surface { id: FORK, attributable: false, default_on: false, desc: "forking this endpoint, mind and all" }, + Surface { + id: FORK, + attributable: false, + default_on: false, + desc: "forking this endpoint, mind and all", + }, ]; /// Every id in the v1 set — the vocabulary a UI or `spt endpoint access` @@ -1461,9 +1511,7 @@ impl AccessStore { pub fn load_checked_from(path: &Path) -> Result { let raw = match std::fs::read_to_string(path) { Ok(s) => s, - Err(e) if e.kind() == std::io::ErrorKind::NotFound => { - return Self::mint_baseline(path) - } + Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Self::mint_baseline(path), Err(e) => { return Err(AccessDegraded { path: path.to_path_buf(), @@ -1812,7 +1860,10 @@ impl AccessStore { /// already opened for somebody. // [impl->REQ-ACL-LOCKED-POSTURE] fn has_allow_hole(&self, endpoint: &str, surface: &str) -> bool { - let endpoint_rules = self.lookup(endpoint).map(|e| e.rules.as_slice()).unwrap_or(&[]); + let endpoint_rules = self + .lookup(endpoint) + .map(|e| e.rules.as_slice()) + .unwrap_or(&[]); endpoint_rules .iter() .chain(self.node.rules.iter()) @@ -1949,23 +2000,21 @@ impl AccessStore { &mut self.endpoint_mut(mutation.scope.word()).rules }; match mutation.op { - MutationOp::Upsert => { - match rules.iter_mut().find(|r| r.same_tuple(&mutation.rule)) { - Some(slot) => { - let changed = slot.decision != mutation.rule.decision; - *slot = mutation.rule.clone(); - if changed { - MutationEffect::Replaced - } else { - MutationEffect::Unchanged - } - } - None => { - rules.push(mutation.rule.clone()); - MutationEffect::Added + MutationOp::Upsert => match rules.iter_mut().find(|r| r.same_tuple(&mutation.rule)) { + Some(slot) => { + let changed = slot.decision != mutation.rule.decision; + *slot = mutation.rule.clone(); + if changed { + MutationEffect::Replaced + } else { + MutationEffect::Unchanged } } - } + None => { + rules.push(mutation.rule.clone()); + MutationEffect::Added + } + }, MutationOp::Remove => { let before = rules.len(); rules.retain(|r| !r.same_tuple(&mutation.rule)); @@ -2155,7 +2204,11 @@ impl AccessStore { /// mode-change gossip never reaches this writer. // [impl->REQ-ACL-SUBNET-MODE-CAPTURE] pub fn capture_subnet_mode(&mut self, subnet: &str, mode: Mode) { - match self.captured_subnets.iter_mut().find(|c| c.subnet == subnet) { + match self + .captured_subnets + .iter_mut() + .find(|c| c.subnet == subnet) + { Some(c) => c.modes.set_all(mode), None => { let mut modes = Modes::default(); @@ -2490,7 +2543,10 @@ mod tests { .unwrap_err(); assert!(matches!(err, MutationRefusal::NeedsAdmitNode { .. })); assert!(err.to_string().contains("beef"), "{err}"); - assert!(s.lookup("ling").is_none(), "a refused mutation writes nothing"); + assert!( + s.lookup("ling").is_none(), + "a refused mutation writes nothing" + ); // With it ⇒ applied. assert_eq!( @@ -2504,7 +2560,8 @@ mod tests { ..AccessStore::default() }; assert_eq!( - s2.apply_mutation(&m, Authority::SameNodeUser, false).unwrap(), + s2.apply_mutation(&m, Authority::SameNodeUser, false) + .unwrap(), MutationEffect::Added, "a same-node user is node-sovereign" ); @@ -2536,7 +2593,8 @@ mod tests { assert_eq!(open.endpoints_can_grant_nodes, None); assert_eq!(open.effective_posture("ling", surface::MSG), Mode::Open); assert_eq!( - open.apply_mutation(&m, Authority::OwnerAgent, true).unwrap(), + open.apply_mutation(&m, Authority::OwnerAgent, true) + .unwrap(), MutationEffect::Added ); @@ -2551,13 +2609,18 @@ mod tests { assert!(matches!(err, MutationRefusal::PolicyForbids { .. })); let msg = err.to_string(); assert!(msg.contains("closed"), "names the posture: {msg}"); - assert!(msg.contains("engine room"), "names the seat that can: {msg}"); + assert!( + msg.contains("engine room"), + "names the seat that can: {msg}" + ); // An EXPLICIT true overrides the closed-posture derivation — explicit // always wins over derived. closed.endpoints_can_grant_nodes = Some(true); assert_eq!( - closed.apply_mutation(&m, Authority::OwnerAgent, true).unwrap(), + closed + .apply_mutation(&m, Authority::OwnerAgent, true) + .unwrap(), MutationEffect::Added ); } @@ -2591,7 +2654,8 @@ mod tests { node_rule("beef", RuleDecision::Allow, &[surface::MSG]), ); assert_eq!( - s.apply_mutation(&narrow, Authority::OwnerAgent, true).unwrap(), + s.apply_mutation(&narrow, Authority::OwnerAgent, true) + .unwrap(), MutationEffect::Added ); } @@ -2615,7 +2679,9 @@ mod tests { endpoints_can_grant_nodes: Some(true), ..AccessStore::default() }; - let err = s.apply_mutation(&m, Authority::OwnerAgent, true).unwrap_err(); + let err = s + .apply_mutation(&m, Authority::OwnerAgent, true) + .unwrap_err(); assert_eq!(err, MutationRefusal::NodeScopeIsEngineRoomOnly); let msg = err.to_string(); assert!(msg.contains("engine room"), "{msg}"); @@ -2632,12 +2698,16 @@ mod tests { MutationEffect::Added ); assert_eq!(s.node.rules.len(), 1); - assert!(s.endpoints.is_empty(), "node scope is not an endpoint record"); + assert!( + s.endpoints.is_empty(), + "node scope is not an endpoint record" + ); // A same-node user may too — node-sovereign, the emergency lever. let mut s2 = AccessStore::default(); assert_eq!( - s2.apply_mutation(&m, Authority::SameNodeUser, false).unwrap(), + s2.apply_mutation(&m, Authority::SameNodeUser, false) + .unwrap(), MutationEffect::Added ); @@ -2903,7 +2973,9 @@ mod tests { let n1 = r#"{"subject":{"kind":"node","node":"beef"},"decision":"allow"}"#; let decoded: AccessRule = serde_json::from_str(n1).unwrap(); assert_eq!(decoded.provenance, Provenance::Manual); - assert!(!serde_json::to_string(&decoded).unwrap().contains("provenance")); + assert!(!serde_json::to_string(&decoded) + .unwrap() + .contains("provenance")); } // [unit->REQ-ACL-RULE-MUTATION] upserting the opposite decision for one @@ -2936,7 +3008,11 @@ mod tests { MutationEffect::Replaced ); let rules = &s.lookup("ling").unwrap().rules; - assert_eq!(rules.len(), 1, "one tuple, one rule — never a contradictory pair"); + assert_eq!( + rules.len(), + 1, + "one tuple, one rule — never a contradictory pair" + ); assert_eq!(rules[0].decision, RuleDecision::Deny); } @@ -2949,7 +3025,10 @@ mod tests { fn the_v1_vocabulary_is_derived_from_the_surface_table() { let from_table: Vec<&str> = surface::TABLE.iter().map(|s| s.id).collect(); let derived: Vec<&str> = surface::v1().collect(); - assert_eq!(derived, from_table, "v1() must BE the table's ids, in order"); + assert_eq!( + derived, from_table, + "v1() must BE the table's ids, in order" + ); assert_eq!(derived.len(), surface::TABLE.len()); } @@ -2995,8 +3074,18 @@ mod tests { use surface::Surface; // XFER attributable, MSG not — the inverse of today's snapshot. let flipped = &[ - Surface { id: surface::MSG, attributable: false, default_on: false, desc: "fixture msg" }, - Surface { id: surface::XFER, attributable: true, default_on: false, desc: "fixture xfer" }, + Surface { + id: surface::MSG, + attributable: false, + default_on: false, + desc: "fixture msg", + }, + Surface { + id: surface::XFER, + attributable: true, + default_on: false, + desc: "fixture xfer", + }, ]; assert!( surface::attributable_in(flipped, surface::XFER), @@ -3015,7 +3104,6 @@ mod tests { surface::attributable_in(surface::TABLE, row.id) ); } - } // [unit->REQ-ACL-DISCOVER-DEFAULT-ON] the default-on reader is a FUNCTION OF @@ -3031,8 +3119,18 @@ mod tests { fn the_default_on_reader_follows_the_table_not_a_hardcoded_id() { use surface::Surface; let flipped = &[ - Surface { id: surface::MSG, attributable: true, default_on: true, desc: "fixture msg" }, - Surface { id: surface::DISCOVER, attributable: false, default_on: false, desc: "fixture discover" }, + Surface { + id: surface::MSG, + attributable: true, + default_on: true, + desc: "fixture msg", + }, + Surface { + id: surface::DISCOVER, + attributable: false, + default_on: false, + desc: "fixture discover", + }, ]; assert!( surface::default_on_in(flipped, surface::MSG), @@ -3088,7 +3186,10 @@ mod tests { ); let m = s.decide(&req("ling", surface::MSG, "aa11", &subnets)); - assert!(!m.allow, "the blanket posture still governs every other surface"); + assert!( + !m.allow, + "the blanket posture still governs every other surface" + ); assert_eq!(m.tier, MatchedTier::NodeMode); } @@ -3106,7 +3207,10 @@ mod tests { let mut ep = AccessStore::default(); ep.set_endpoint_surface_mode("ling", surface::DISCOVER, Mode::Closed); let v = ep.decide(&req("ling", surface::DISCOVER, "aa11", &subnets)); - assert!(!v.allow, "an endpoint that named DISCOVER closed still closes it"); + assert!( + !v.allow, + "an endpoint that named DISCOVER closed still closes it" + ); assert_eq!(v.tier, MatchedTier::EndpointMode); assert!( ep.decide(&req("doyle", surface::DISCOVER, "aa11", &subnets)) @@ -3121,7 +3225,10 @@ mod tests { .per_surface .insert(surface::DISCOVER.to_string(), Mode::Closed); let v = node.decide(&req("ling", surface::DISCOVER, "aa11", &subnets)); - assert!(!v.allow, "a node that named DISCOVER closed still closes it"); + assert!( + !v.allow, + "a node that named DISCOVER closed still closes it" + ); assert_eq!(v.tier, MatchedTier::NodeMode); // Tier 8 — the join-time-captured subnet mode. @@ -3132,7 +3239,10 @@ mod tests { .per_surface .insert(surface::DISCOVER.to_string(), Mode::Closed); let v = cap.decide(&req("ling", surface::DISCOVER, "aa11", &subnets)); - assert!(!v.allow, "a captured subnet that named DISCOVER closed still closes it"); + assert!( + !v.allow, + "a captured subnet that named DISCOVER closed still closes it" + ); assert_eq!(v.tier, MatchedTier::CapturedSubnetMode); } @@ -3150,7 +3260,10 @@ mod tests { .push(node_rule("aa11", RuleDecision::Deny, &[surface::DISCOVER])); let v = s.decide(&req("ling", surface::DISCOVER, "aa11", &subnets)); - assert!(!v.allow, "an explicit DISCOVER deny row is the off-switch that survives"); + assert!( + !v.allow, + "an explicit DISCOVER deny row is the off-switch that survives" + ); assert!(matches!(v.tier, MatchedTier::NodeScopeRule(_))); assert!( s.decide(&req("ling", surface::DISCOVER, "bb22", &subnets)) @@ -3207,7 +3320,10 @@ mod tests { let mut s = AccessStore::default(); s.set_node_mode(Mode::Closed); - assert!(s.decide(&req("ling", surface::DISCOVER, "aa11", &subnets)).allow); + assert!( + s.decide(&req("ling", surface::DISCOVER, "aa11", &subnets)) + .allow + ); assert_eq!( s.effective_posture("ling", surface::DISCOVER), Mode::Open, @@ -3227,9 +3343,11 @@ mod tests { // otherwise the agreement above would be a coincidence of one direction. let mut named = AccessStore::default(); named.set_endpoint_surface_mode("ling", surface::DISCOVER, Mode::Closed); - assert!(!named - .decide(&req("ling", surface::DISCOVER, "aa11", &subnets)) - .allow); + assert!( + !named + .decide(&req("ling", surface::DISCOVER, "aa11", &subnets)) + .allow + ); assert_eq!( named.effective_posture("ling", surface::DISCOVER), Mode::Closed @@ -3276,7 +3394,8 @@ mod tests { MatchedTier::SurfaceDefaultOpen ); assert_eq!( - open.decide(&req("ling", surface::MSG, "aa11", &subnets)).tier, + open.decide(&req("ling", surface::MSG, "aa11", &subnets)) + .tier, MatchedTier::NodeMode, "an ordinary surface still credits the blanket that governed it" ); @@ -3327,8 +3446,18 @@ mod tests { fn the_subject_consequence_follows_the_attributability_flag() { use surface::Surface; let pair = &[ - Surface { id: "BOUND", attributable: true, default_on: false, desc: "same words" }, - Surface { id: "WIDE", attributable: false, default_on: false, desc: "same words" }, + Surface { + id: "BOUND", + attributable: true, + default_on: false, + desc: "same words", + }, + Surface { + id: "WIDE", + attributable: false, + default_on: false, + desc: "same words", + }, ]; let rendered = surface::control_surfaces_in(pair); assert!( @@ -3337,15 +3466,18 @@ mod tests { {rendered}" ); assert!( - rendered.contains( - "WIDE — same words (a grant admits the whole machine)" - ), + rendered.contains("WIDE — same words (a grant admits the whole machine)"), "a non-attributable row must teach the widening BEFORE the refusal; got: {rendered}" ); // The flip promised by the table ("XFER is the expected next") reaches // the operator's sentence with no second edit. - let flipped = &[Surface { id: "WIDE", attributable: true, default_on: false, desc: "same words" }]; + let flipped = &[Surface { + id: "WIDE", + attributable: true, + default_on: false, + desc: "same words", + }]; assert!( surface::control_surfaces_in(flipped) .contains("WIDE — same words (a grant binds the single sender)"), @@ -3620,7 +3752,10 @@ mod tests { "DISCOVER", "FORK", ] { - assert!(surface::v1().any(|s| s == want), "{want} missing from v1 set"); + assert!( + surface::v1().any(|s| s == want), + "{want} missing from v1 set" + ); } // An unminted surface id is legal in a rule and governs only itself. @@ -3744,7 +3879,10 @@ mod tests { let mut s = AccessStore::default(); s.allow_surfaces("ling", "aa11", &[surface::RC_VIEW]); assert!(s.decide(&req("ling", surface::RC_VIEW, "aa11", &[])).allow); - assert!(!s.decide(&req("ling", surface::RC_ATTACH, "aa11", &[])).allow); + assert!( + !s.decide(&req("ling", surface::RC_ATTACH, "aa11", &[])) + .allow + ); assert!(!s.decide(&req("ling", surface::MSG, "aa11", &[])).allow); // An all-surface rule covers everything. @@ -3828,7 +3966,8 @@ mod tests { assert!(!v.allow); assert_eq!(v.tier, MatchedTier::EndpointMode); assert!( - s.decide(&req("doyle", surface::MSG, "aa11", &subnets)).allow, + s.decide(&req("doyle", surface::MSG, "aa11", &subnets)) + .allow, "another endpoint keeps the node mode" ); @@ -3857,7 +3996,10 @@ mod tests { decision: RuleDecision::Deny, }); let v = s.decide(&req("ling", surface::MSG, "aa11", &subnets)); - assert!(!v.allow, "node rule outranks the wildcard in the same scope"); + assert!( + !v.allow, + "node rule outranks the wildcard in the same scope" + ); // Tier 3: a per-endpoint wildcard outranks anything node-scope. s.endpoint_mut("ling").rules.push(AccessRule { @@ -3983,7 +4125,10 @@ mod tests { provenance: Provenance::Manual, decision: RuleDecision::Allow, }); - assert!(s.sender_endpoint_rule_ids().is_empty(), "decoys do not count"); + assert!( + s.sender_endpoint_rule_ids().is_empty(), + "decoys do not count" + ); // One per scope — the scan must see the node scope too, not just endpoints. s.endpoint_mut("ling").rules.push(AccessRule { @@ -3996,9 +4141,7 @@ mod tests { decision: RuleDecision::Deny, }); s.node.rules.push(AccessRule { - subject: Subject::SenderEndpoint { - id: "eve".into(), - }, + subject: Subject::SenderEndpoint { id: "eve".into() }, surfaces: Vec::new(), origin: OriginQualifier::Any, provenance: Provenance::Manual, @@ -4045,7 +4188,10 @@ mod tests { assert!(s.lookup("ling").is_none(), "open deletes the record"); assert!(s.decide(&req("ling", surface::MSG, "bb22", &[])).allow); assert!(!s.open("ling"), "second open no-op"); - assert!(!s.revoke("ghost", "aa11"), "revoke on unrestricted is no-op"); + assert!( + !s.revoke("ghost", "aa11"), + "revoke on unrestricted is no-op" + ); } // [unit->REQ-ACL-POSITIONAL-ALLOW-HONORS-FLAGS] the posture half of the v1 @@ -4413,7 +4559,10 @@ mod tests { let w = REPLY_WINDOW_MS; log.record("ling", "aa11", 1_000, w); - assert!(log.correlates("ling", "aa11", 1_000 + w, w), "inside window"); + assert!( + log.correlates("ling", "aa11", 1_000 + w, w), + "inside window" + ); assert!(!log.correlates("ling", "aa11", 1_001 + w, w), "expired"); assert!( !log.correlates("ling", "bb22", 2_000, w), @@ -4672,7 +4821,13 @@ mod tests { !node.decide(&req("ling", surface::MSG, "aa11", &subnets)).allow, "PRECONDITION: a closed node mode must still refuse the REMOTE peer — if this passes, the cell below proves nothing" ); - let local = node.decide(&req_local("ling", surface::MSG, "beef", &subnets, Some("doyle"))); + let local = node.decide(&req_local( + "ling", + surface::MSG, + "beef", + &subnets, + Some("doyle"), + )); assert!( local.allow, "a closed NODE posture is about the network; it must not close the node in on itself" @@ -4682,12 +4837,19 @@ mod tests { let mut ep = AccessStore::default(); ep.set_endpoint_mode("ling", Mode::Closed); assert!( - !ep.decide(&req("ling", surface::MSG, "aa11", &subnets)).allow, + !ep.decide(&req("ling", surface::MSG, "aa11", &subnets)) + .allow, "PRECONDITION: the endpoint mode still refuses the remote peer" ); assert!( - ep.decide(&req_local("ling", surface::MSG, "beef", &subnets, Some("doyle"))) - .allow, + ep.decide(&req_local( + "ling", + surface::MSG, + "beef", + &subnets, + Some("doyle") + )) + .allow, "nor does a closed ENDPOINT posture reach local traffic" ); @@ -4695,12 +4857,19 @@ mod tests { let mut cap = AccessStore::default(); cap.capture_subnet_mode("work", Mode::Closed); assert!( - !cap.decide(&req("ling", surface::MSG, "aa11", &subnets)).allow, + !cap.decide(&req("ling", surface::MSG, "aa11", &subnets)) + .allow, "PRECONDITION: the captured-subnet mode still refuses the remote peer" ); assert!( - cap.decide(&req_local("ling", surface::MSG, "beef", &subnets, Some("doyle"))) - .allow, + cap.decide(&req_local( + "ling", + surface::MSG, + "beef", + &subnets, + Some("doyle") + )) + .allow, "nor does a captured-subnet posture" ); } @@ -4723,9 +4892,17 @@ mod tests { fn a_rule_naming_the_local_origin_still_governs_it() { let subnets = vec!["work".to_string()]; let mut s = AccessStore::default(); - s.node.rules.push(node_rule("beef", RuleDecision::Deny, &[surface::MSG])); + s.node + .rules + .push(node_rule("beef", RuleDecision::Deny, &[surface::MSG])); - let v = s.decide(&req_local("ling", surface::MSG, "beef", &subnets, Some("doyle"))); + let v = s.decide(&req_local( + "ling", + surface::MSG, + "beef", + &subnets, + Some("doyle"), + )); assert!( !v.allow, "an explicit DENY naming this origin refuses it — the abstention scopes the blanket postures, it does not exempt local traffic from the chain" @@ -4737,7 +4914,13 @@ mod tests { ); // The bottom is still reachable for anything the rule does not name. - let other = s.decide(&req_local("ling", surface::XFER, "beef", &subnets, Some("doyle"))); + let other = s.decide(&req_local( + "ling", + surface::XFER, + "beef", + &subnets, + Some("doyle"), + )); assert!( other.allow, "a surface the rule does not name falls through to the chain bottom" @@ -4765,24 +4948,41 @@ mod tests { fn a_per_endpoint_own_node_allow_reopens_one_target_through_a_node_wide_deny() { let subnets = vec!["work".to_string()]; let mut s = AccessStore::default(); - s.node.rules.push(node_rule("beef", RuleDecision::Deny, &[surface::MSG])); + s.node + .rules + .push(node_rule("beef", RuleDecision::Deny, &[surface::MSG])); s.endpoint_mut("ling") .rules .push(node_rule("beef", RuleDecision::Allow, &[surface::MSG])); - let reopened = s.decide(&req_local("ling", surface::MSG, "beef", &subnets, Some("doyle"))); + let reopened = s.decide(&req_local( + "ling", + surface::MSG, + "beef", + &subnets, + Some("doyle"), + )); assert!( reopened.allow, "the per-endpoint allow must answer before the node-wide deny" ); assert!( - matches!(&reopened.tier, MatchedTier::EndpointRule(Subject::Node { .. })), + matches!( + &reopened.tier, + MatchedTier::EndpointRule(Subject::Node { .. }) + ), "and it is the ENDPOINT-scope rule tier that answered: {:?}", reopened.tier ); // The deny is not gone — every other hosted endpoint is still closed. - let elsewhere = s.decide(&req_local("mona", surface::MSG, "beef", &subnets, Some("doyle"))); + let elsewhere = s.decide(&req_local( + "mona", + surface::MSG, + "beef", + &subnets, + Some("doyle"), + )); assert!( !elsewhere.allow, "the node-wide own-node deny still governs endpoints the allow does \ @@ -4804,7 +5004,9 @@ mod tests { fn a_sender_rule_is_more_specific_than_both_own_node_denies() { let subnets = vec!["work".to_string()]; let mut s = AccessStore::default(); - s.node.rules.push(node_rule("beef", RuleDecision::Deny, &[surface::MSG])); + s.node + .rules + .push(node_rule("beef", RuleDecision::Deny, &[surface::MSG])); s.endpoint_mut("ling") .rules .push(node_rule("beef", RuleDecision::Deny, &[surface::MSG])); @@ -4818,7 +5020,13 @@ mod tests { decision: RuleDecision::Allow, }); - let named = s.decide(&req_local("ling", surface::MSG, "beef", &subnets, Some("doyle"))); + let named = s.decide(&req_local( + "ling", + surface::MSG, + "beef", + &subnets, + Some("doyle"), + )); assert!( named.allow, "the sender the rule names is admitted through both own-node denies" @@ -4832,7 +5040,13 @@ mod tests { named.tier ); - let unnamed = s.decide(&req_local("ling", surface::MSG, "beef", &subnets, Some("mona"))); + let unnamed = s.decide(&req_local( + "ling", + surface::MSG, + "beef", + &subnets, + Some("mona"), + )); assert!( !unnamed.allow, "a sender the rule does not name is still refused by the own-node \ @@ -4857,11 +5071,20 @@ mod tests { fn an_own_node_deny_leaves_remote_origins_untouched() { let subnets = vec!["work".to_string()]; let mut s = AccessStore::default(); - s.node.rules.push(node_rule("beef", RuleDecision::Deny, &[surface::MSG])); + s.node + .rules + .push(node_rule("beef", RuleDecision::Deny, &[surface::MSG])); // Non-vacuity: the same store refuses the local origin it names. assert!( - !s.decide(&req_local("ling", surface::MSG, "beef", &subnets, Some("doyle"))).allow, + !s.decide(&req_local( + "ling", + surface::MSG, + "beef", + &subnets, + Some("doyle") + )) + .allow, "PRECONDITION: the own-node deny must actually be refusing local \ traffic on this store, or the remote pass below proves nothing" ); @@ -5065,7 +5288,8 @@ mod tests { let mut s = AccessStore::default(); s.set_endpoint_mode("shut", Mode::Closed); assert!( - s.decide(&req("shut", surface::DISCOVER, "anyone", &[])).allow, + s.decide(&req("shut", surface::DISCOVER, "anyone", &[])) + .allow, "precondition: a blanket close does not govern the one default-on row", ); assert!( diff --git a/crates/spt-store/src/atomic.rs b/crates/spt-store/src/atomic.rs index 457460c8..146a83dc 100644 --- a/crates/spt-store/src/atomic.rs +++ b/crates/spt-store/src/atomic.rs @@ -229,7 +229,10 @@ mod tests { .filter_map(|e| e.file_name().into_string().ok()) .filter(|n| n.contains(".tmp")) .collect(); - assert!(leftover.is_empty(), "no *.tmp* sibling may remain: {leftover:?}"); + assert!( + leftover.is_empty(), + "no *.tmp* sibling may remain: {leftover:?}" + ); } fn sharing_violation() -> io::Error { @@ -283,7 +286,10 @@ mod tests { let s_target = dir.path().join("rec.json"); atomic_write_string_durable(&s_target, "{\"id\":\"hall-a\"}").unwrap(); - assert_eq!(fs::read_to_string(&s_target).unwrap(), "{\"id\":\"hall-a\"}"); + assert_eq!( + fs::read_to_string(&s_target).unwrap(), + "{\"id\":\"hall-a\"}" + ); no_tmp_sibling_remains(dir.path()); } diff --git a/crates/spt-store/src/attachment.rs b/crates/spt-store/src/attachment.rs index f1823b0e..1f59fdae 100644 --- a/crates/spt-store/src/attachment.rs +++ b/crates/spt-store/src/attachment.rs @@ -154,8 +154,12 @@ mod tests { assert!(!att.is_detached("home")); let mut store = SubnetStore::default(); - store.create_subnet("home", crate::access::Mode::Open).unwrap(); - store.create_subnet("work", crate::access::Mode::Open).unwrap(); + store + .create_subnet("home", crate::access::Mode::Open) + .unwrap(); + store + .create_subnet("work", crate::access::Mode::Open) + .unwrap(); att.filter_serving(&mut store); assert!(store.find("home").is_some(), "attached survives the view"); assert!( diff --git a/crates/spt-store/src/branchstore.rs b/crates/spt-store/src/branchstore.rs index 980b2493..87d71e68 100644 --- a/crates/spt-store/src/branchstore.rs +++ b/crates/spt-store/src/branchstore.rs @@ -677,7 +677,12 @@ fn config_set_locked_retry(dir: &str, key: &str, value: &str) -> std::io::Result // Already set (a racer won)? Skip the write — this cuts the herd so N // racers don't all pile onto the shared config under contention. A // transient read failure here is ignored (fall through to the write). - if let Ok(out) = run_git(&["-C", dir, "config", "--get", key], None, None, GIT_TIMEOUT) { + if let Ok(out) = run_git( + &["-C", dir, "config", "--get", key], + None, + None, + GIT_TIMEOUT, + ) { if out.success() && out.stdout_trimmed() == value { return Ok(()); } @@ -732,11 +737,15 @@ mod tests { "warning: unable to access 'config'\n\ fatal: unknown error occurred while reading the configuration files" )); - assert!(config_error_is_retryable("fatal: could not read config file config")); + assert!(config_error_is_retryable( + "fatal: could not read config file config" + )); // Case-insensitive. assert!(config_error_is_retryable("COULD NOT LOCK CONFIG FILE")); // Genuine, non-transient errors fail fast (NOT retryable). - assert!(!config_error_is_retryable("fatal: bad config line 1 in file config")); + assert!(!config_error_is_retryable( + "fatal: bad config line 1 in file config" + )); assert!(!config_error_is_retryable( "error: key does not contain a section: foo" )); @@ -755,7 +764,10 @@ mod tests { // Isolation guard: the fixture MUST be an absolute path UNDER the TempDir // and NEVER resolve under cwd — a store path that defaults to cwd would // `git init` the working tree (droppings at the project root). - assert!(git_dir.is_absolute(), "fixture must be absolute: {git_dir:?}"); + assert!( + git_dir.is_absolute(), + "fixture must be absolute: {git_dir:?}" + ); assert!( git_dir.starts_with(dir.path()), "fixture must live under the TempDir: {git_dir:?}" @@ -923,7 +935,9 @@ mod tests { let wt_old = tmp.path().join("wt-old"); s.ensure_worktree("p-old", &wt_old).unwrap(); std::fs::write(wt_old.join("f.md"), "old").unwrap(); - s.commit_in_worktree(&wt_old, &["f.md"], "old").unwrap().unwrap(); + s.commit_in_worktree(&wt_old, &["f.md"], "old") + .unwrap() + .unwrap(); std::thread::sleep(std::time::Duration::from_millis(1100)); @@ -931,12 +945,17 @@ mod tests { let wt_new = tmp.path().join("wt-new"); s.ensure_worktree("p-new", &wt_new).unwrap(); std::fs::write(wt_new.join("f.md"), "new").unwrap(); - s.commit_in_worktree(&wt_new, &["f.md"], "new").unwrap().unwrap(); + s.commit_in_worktree(&wt_new, &["f.md"], "new") + .unwrap() + .unwrap(); let order = s.branches_by_recency().unwrap(); let p_new = order.iter().position(|b| b == "p-new").unwrap(); let p_old = order.iter().position(|b| b == "p-old").unwrap(); - assert!(p_new < p_old, "newest-committed branch sorts first: {order:?}"); + assert!( + p_new < p_old, + "newest-committed branch sorts first: {order:?}" + ); // Same membership as the unsorted enumeration. let mut a = order.clone(); let mut b = s.branches().unwrap(); @@ -961,7 +980,11 @@ mod tests { let pairs = s.branch_tips_by_recency().unwrap(); let names: Vec = pairs.iter().map(|(b, _)| b.clone()).collect(); - assert_eq!(names, s.branches_by_recency().unwrap(), "same recency order"); + assert_eq!( + names, + s.branches_by_recency().unwrap(), + "same recency order" + ); for (branch, tip) in &pairs { assert_eq!( s.tip(branch).unwrap().as_deref(), diff --git a/crates/spt-store/src/briefing.rs b/crates/spt-store/src/briefing.rs index 0f88e5bb..4060dc42 100644 --- a/crates/spt-store/src/briefing.rs +++ b/crates/spt-store/src/briefing.rs @@ -177,7 +177,10 @@ fn subject_word(subject: &Subject) -> String { /// (or an empty string) is treated as having answered nothing — a blank label /// would render `node:` and read as a rule about nobody. // [impl->REQ-ER-RULESET-NODE-NAMES] -fn subject_label_of(subject: &Subject, resolve: &impl Fn(&str) -> Option) -> Option { +fn subject_label_of( + subject: &Subject, + resolve: &impl Fn(&str) -> Option, +) -> Option { match subject { Subject::Node { node } => resolve(node) .map(|l| l.trim().to_string()) @@ -324,8 +327,10 @@ pub fn node_label_map() -> std::collections::BTreeMap { .collect(); // `load_existing`, never `load_or_create`: resolving a name for a view must // not MINT this node's identity as a side effect of rendering a table. - if let (Some(id), Some(host)) = (crate::nodeid::load_existing(), crate::hostlabel::os_hostname()) - { + if let (Some(id), Some(host)) = ( + crate::nodeid::load_existing(), + crate::hostlabel::os_hostname(), + ) { labels.insert(id.public_key().to_hex().to_lowercase(), host); } labels @@ -416,7 +421,13 @@ pub fn render_ruleset_table(rows: &[RulesetRow]) -> String { // Width in CHARS, not bytes: a multi-byte label would pad short by the // difference and the terminal column would wander. let widths: Vec = (0..COLS) - .map(|c| cells.iter().map(|row| row[c].chars().count()).max().unwrap_or(0)) + .map(|c| { + cells + .iter() + .map(|row| row[c].chars().count()) + .max() + .unwrap_or(0) + }) .collect(); let pad = |text: &str, width: usize| { let mut cell = text.to_string(); @@ -536,9 +547,13 @@ pub fn compose_briefing(facts: &BriefingFacts) -> String { b.push('\n'); if facts.pending.is_empty() { - b.push_str("Pending declarations: none — every subnet you hold is enforcing what it declares.\n"); + b.push_str( + "Pending declarations: none — every subnet you hold is enforcing what it declares.\n", + ); } else { - b.push_str("Pending declarations (seen, NOT adopted — this node still enforces the old one):\n"); + b.push_str( + "Pending declarations (seen, NOT adopted — this node still enforces the old one):\n", + ); for (subnet, mode) in &facts.pending { b.push_str(&format!( " {subnet} now declares {} — `spt api access-refresh {subnet} engine-room` adopts it\n", @@ -556,7 +571,9 @@ pub fn compose_briefing(facts: &BriefingFacts) -> String { // today still needs to know the verb exists, and the block above teaches it // only in the one case where a delta happens to be waiting. // [impl->REQ-ACL-ACCESS-REFRESH-ER-ONLY] - b.push_str(" spt api access-refresh adopt a posture that subnet declares\n\n"); + b.push_str( + " spt api access-refresh adopt a posture that subnet declares\n\n", + ); // NO surface vocabulary here. It moved to the durable in-core role // (REQ-ER-BRIEFING-SURFACE-VOCAB, amended by replacement 2026-08-19): the @@ -813,7 +830,10 @@ mod tests { body.contains("bignet now declares closed"), "the pending delta is stated, with the verb that adopts it: {body}" ); - assert!(body.contains("SCOPE"), "the ruleset table rides along: {body}"); + assert!( + body.contains("SCOPE"), + "the ruleset table rides along: {body}" + ); // No delta pending is stated positively too — a briefing that simply // omits the section leaves "nothing pending" and "not checked" @@ -853,7 +873,10 @@ mod tests { let rows = ruleset_rows(&store); assert_eq!(rows.len(), 1); - assert_eq!(rows[0].provenance, "knock-approve", "the row carries its origin story"); + assert_eq!( + rows[0].provenance, "knock-approve", + "the row carries its origin story" + ); assert_eq!(rows[0].origin.as_deref(), Some("user")); assert_eq!( rows[0].remove, @@ -862,7 +885,10 @@ mod tests { ); let text = render_ruleset_drilldown(&rows); - assert!(text.contains("ORIGIN"), "the table gained the qualifier column:\n{text}"); + assert!( + text.contains("ORIGIN"), + "the table gained the qualifier column:\n{text}" + ); assert!(text.contains("FROM"), "and the provenance column:\n{text}"); assert!(text.contains("knock-approve"), "{text}"); assert!(text.contains("to remove:"), "{text}"); diff --git a/crates/spt-store/src/commune_intent.rs b/crates/spt-store/src/commune_intent.rs index 2aac44c0..f7acb37f 100644 --- a/crates/spt-store/src/commune_intent.rs +++ b/crates/spt-store/src/commune_intent.rs @@ -128,7 +128,11 @@ mod tests { ); consume_intent(perch); - assert_eq!(read_intent(perch), None, "an ingest consumes the expectation"); + assert_eq!( + read_intent(perch), + None, + "an ingest consumes the expectation" + ); } // [unit->REQ-PSYCHE-INGEST-INTENT-MARKER] the orphan predicate, including the @@ -151,7 +155,10 @@ mod tests { assert!(!is_orphaned(&intent, 10_000 + 89_000, false)); // Exactly at the budget is not past it; a millisecond later is. - assert!(!intent.is_past_budget(10_000 + 90_000), "at the bound is not past it"); + assert!( + !intent.is_past_budget(10_000 + 90_000), + "at the bound is not past it" + ); assert!(intent.is_past_budget(10_000 + 90_001)); // Past the budget with NO drop: the artifact-less death this marker exists for. diff --git a/crates/spt-store/src/contacts.rs b/crates/spt-store/src/contacts.rs index aef4de98..8530f9fd 100644 --- a/crates/spt-store/src/contacts.rs +++ b/crates/spt-store/src/contacts.rs @@ -139,17 +139,13 @@ impl ContactLedger { /// are two rows rather than one that keeps overwriting itself. Prunes rows /// past [`CONTACT_WINDOW_MS`] and enforces [`CONTACT_CAP`] oldest-first. // [impl->REQ-UNLISTED-CONTACT-LEDGER] - pub fn record( - &mut self, - direction: ContactDirection, - endpoint: &str, - node: &str, - now_ms: u64, - ) { + pub fn record(&mut self, direction: ContactDirection, endpoint: &str, node: &str, now_ms: u64) { self.prune(now_ms); - match self.rows.iter_mut().find(|r| { - r.direction == direction && r.endpoint == endpoint && r.node == node - }) { + match self + .rows + .iter_mut() + .find(|r| r.direction == direction && r.endpoint == endpoint && r.node == node) + { Some(r) => r.last_seen_ms = now_ms, None => self.rows.push(ContactRow { direction, @@ -233,7 +229,11 @@ mod tests { // READ side: the stale row never surfaces even though nothing wrote. let seen: Vec<&str> = led.recent(now).map(|r| r.endpoint.as_str()).collect(); - assert_eq!(seen, vec!["doyle"], "a 15-day-old row is outside the window"); + assert_eq!( + seen, + vec!["doyle"], + "a 15-day-old row is outside the window" + ); // WRITE side: an unrelated record prunes it from the file. led.record(ContactDirection::Outbound, "perri", "n3", now); @@ -363,7 +363,10 @@ mod tests { offenders.push(path.display().to_string()); } } - assert!(scanned > 0, "scanned no wire sources — the walk was vacuous"); + assert!( + scanned > 0, + "scanned no wire sources — the walk was vacuous" + ); assert!( offenders.is_empty(), "the contact ledger must ride no wire record: {offenders:?}" diff --git a/crates/spt-store/src/contextstore.rs b/crates/spt-store/src/contextstore.rs index 67b21cbf..1dd72738 100644 --- a/crates/spt-store/src/contextstore.rs +++ b/crates/spt-store/src/contextstore.rs @@ -861,10 +861,7 @@ mod tests { ] { assert_eq!( cs2.branch_store() - .read_at_tip( - &agent_branch("doyle-2-fork"), - &format!("monics/{peer}") - ) + .read_at_tip(&agent_branch("doyle-2-fork"), &format!("monics/{peer}")) .unwrap(), Some(text.as_bytes().to_vec()), "the fork must carry the source's monic about {peer}" diff --git a/crates/spt-store/src/dispatchresults.rs b/crates/spt-store/src/dispatchresults.rs index c7b692f6..9708125b 100644 --- a/crates/spt-store/src/dispatchresults.rs +++ b/crates/spt-store/src/dispatchresults.rs @@ -220,7 +220,10 @@ mod tests { fn no_file_reads_as_no_results() { let dir = tempfile::tempdir().unwrap(); assert!(read_all_at(dir.path()).is_empty()); - assert!(append_at(dir.path(), &[]).is_ok(), "an empty append is a no-op"); + assert!( + append_at(dir.path(), &[]).is_ok(), + "an empty append is a no-op" + ); assert!(!results_file_at(dir.path()).exists(), "…and writes no file"); } } @@ -258,7 +261,10 @@ mod vocabulary_tests { let got = read_all_at(dir.path()); assert_eq!(got.len(), 2, "both seal rows land: {got:?}"); - assert!(got.iter().all(|r| r.target.is_none()), "a seal is about TEXT, not a recipient"); + assert!( + got.iter().all(|r| r.target.is_none()), + "a seal is about TEXT, not a recipient" + ); assert_eq!(got[0].status, DispatchStatus::SealMinted); assert_eq!( got[1].status, diff --git a/crates/spt-store/src/empower.rs b/crates/spt-store/src/empower.rs index ccce56d6..420d06b3 100644 --- a/crates/spt-store/src/empower.rs +++ b/crates/spt-store/src/empower.rs @@ -181,7 +181,10 @@ pub enum CarryOutcome { /// The old record could neither be removed nor emptied, so it may still /// GRANT. Nothing was written at the new session id — authority is at one /// session id at most, but this is the one outcome that needs a human. - Stranded { path: std::path::PathBuf, why: String }, + Stranded { + path: std::path::PathBuf, + why: String, + }, } /// How [`neutralize_at`] managed to make a record stop granting. @@ -452,7 +455,8 @@ mod tests { /// A private sessions tree for a carry test — two session dirs under one /// root, so `from` and `to` are the shapes production hands the carry. fn carry_dirs(name: &str) -> (PathBuf, PathBuf, PathBuf) { - let root = std::env::temp_dir().join(format!("spt-emp-carry-{name}-{}", std::process::id())); + let root = + std::env::temp_dir().join(format!("spt-emp-carry-{name}-{}", std::process::id())); let _ = std::fs::remove_dir_all(&root); std::fs::create_dir_all(root.join("alpha")).unwrap(); let from = root.join("alpha").join("empowerments.json"); @@ -626,11 +630,22 @@ mod tests { // A session dir with no empowerments at all is untouched and uncounted. std::fs::create_dir_all(root.join("bare")).expect("bare session dir"); - assert_eq!(sweep_other_sessions_in(&root, "live"), 2, "both leftovers went"); + assert_eq!( + sweep_other_sessions_in(&root, "live"), + 2, + "both leftovers went" + ); assert!(root.join("live").join("empowerments.json").exists()); assert!(!root.join("dead-1").join("empowerments.json").exists()); - assert!(root.join("bare").exists(), "the sweep removes files, not sessions"); - assert_eq!(sweep_other_sessions_in(&root, "live"), 0, "and it is idempotent"); + assert!( + root.join("bare").exists(), + "the sweep removes files, not sessions" + ); + assert_eq!( + sweep_other_sessions_in(&root, "live"), + 0, + "and it is idempotent" + ); assert_eq!( sweep_other_sessions_in(&root.join("nope"), "live"), 0, diff --git a/crates/spt-store/src/engineroom.rs b/crates/spt-store/src/engineroom.rs index 480a7f78..b8cc4c85 100644 --- a/crates/spt-store/src/engineroom.rs +++ b/crates/spt-store/src/engineroom.rs @@ -642,14 +642,22 @@ mod tests { // [unit->REQ-ER-BRINGUP-ATTEMPT-BOUND] #[test] fn backoff_doubles_from_one_second_and_caps_at_an_hour() { - assert_eq!(backoff_ms(0), 0, "an unblemished ledger does not shut the gate"); + assert_eq!( + backoff_ms(0), + 0, + "an unblemished ledger does not shut the gate" + ); assert_eq!(backoff_ms(1), 1_000); assert_eq!(backoff_ms(2), 2_000); assert_eq!(backoff_ms(3), 4_000); assert_eq!(backoff_ms(4), 8_000); assert_eq!(backoff_ms(12), 2_048_000); assert_eq!(backoff_ms(13), BACKOFF_CAP_MS, "doubling stops at the cap"); - assert_eq!(backoff_ms(64), BACKOFF_CAP_MS, "and never overflows past it"); + assert_eq!( + backoff_ms(64), + BACKOFF_CAP_MS, + "and never overflows past it" + ); assert_eq!(backoff_ms(u32::MAX), BACKOFF_CAP_MS); } @@ -700,7 +708,10 @@ mod tests { // throttle answers before verification is consulted, so a shut gate is // not an oracle. let correct_but_early = classify_attempt(&ledger, 1_400, RIGHT); - assert_eq!(correct_but_early, GateOutcome::Throttled { retry_in_ms: 600 }); + assert_eq!( + correct_but_early, + GateOutcome::Throttled { retry_in_ms: 600 } + ); } // An ABSENT code is refused and NOT counted, and the ledger it leaves behind @@ -854,7 +865,10 @@ mod tests { let (again, outcome) = provision_at(&path, "othernet", "codex-spt", 200).expect("reset"); assert_eq!(outcome, ProvisionOutcome::Reset); - assert_eq!(again.home_subnet, "othernet", "the reset is the only re-home path"); + assert_eq!( + again.home_subnet, "othernet", + "the reset is the only re-home path" + ); assert_eq!(again.adapter, "codex-spt"); assert_eq!( EngineRoom::load_from(&path).map(|r| r.home_subnet), @@ -876,7 +890,10 @@ mod tests { #[test] fn the_reserved_id_refusal_is_one_sentence_naming_the_one_entry() { let refusal = reserved_id_refusal(ENGINE_ROOM_ID).expect("the reserved id is refused"); - assert!(refusal.contains(ENGINE_ROOM_ID), "it names the id: {refusal}"); + assert!( + refusal.contains(ENGINE_ROOM_ID), + "it names the id: {refusal}" + ); assert!( refusal.contains(&format!("spt rc {ENGINE_ROOM_ID}")), "it names the bring-up as the only entry: {refusal}" @@ -902,7 +919,10 @@ mod tests { let path = tmp("whitelist"); let _ = std::fs::remove_file(&path); let (mut room, _) = provision_at(&path, "bignet", "claude-spt", 100).expect("mint"); - assert!(!room.advertises_to("aa11"), "advertised to no one by default"); + assert!( + !room.advertises_to("aa11"), + "advertised to no one by default" + ); assert!(!room.advertises_to_anyone(), "…which is a whole-round no"); room.advertise_to.push("aa11".into()); room.save_to(&path).expect("save"); diff --git a/crates/spt-store/src/enroll.rs b/crates/spt-store/src/enroll.rs index d1521f8d..a372ee7d 100644 --- a/crates/spt-store/src/enroll.rs +++ b/crates/spt-store/src/enroll.rs @@ -53,7 +53,9 @@ pub const NODE_SHORT_HEX_LEN: usize = 8; // [impl->REQ-SEAL-ENROLL-RECORD-SUBNET-MATERIAL] pub fn is_node_short_hex(node: &str) -> bool { node.len() == NODE_SHORT_HEX_LEN - && node.bytes().all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b)) + && node + .bytes() + .all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b)) } /// One authenticator enrollment: the durable record that a TOTP ceremony @@ -319,8 +321,9 @@ fn verify_hello_rs256( use sha2::{Digest, Sha256}; let der = hex_bytes(pubkey_hex).map_err(SigVerifyRefusal::BadMaterial)?; let sig = hex_bytes(signature_hex).map_err(SigVerifyRefusal::BadMaterial)?; - let key = RsaPublicKey::from_public_key_der(&der) - .map_err(|e| SigVerifyRefusal::BadMaterial(format!("not a DER SubjectPublicKeyInfo ({e})")))?; + let key = RsaPublicKey::from_public_key_der(&der).map_err(|e| { + SigVerifyRefusal::BadMaterial(format!("not a DER SubjectPublicKeyInfo ({e})")) + })?; let digest = Sha256::digest(payload); key.verify(Pkcs1v15Sign::new::(), &digest, &sig) .map_err(|_| SigVerifyRefusal::SignatureInvalid) @@ -346,8 +349,15 @@ mod tests { #[test] fn mint_persists_and_finds_by_node_subnet() { let mut s = EnrollStore::default(); - let rec = mint_enrollment(&mut s, "ab12cd34ef", "aa11bb22", "home", "hello-kcm-rs256", 42) - .unwrap(); + let rec = mint_enrollment( + &mut s, + "ab12cd34ef", + "aa11bb22", + "home", + "hello-kcm-rs256", + 42, + ) + .unwrap(); assert_eq!(rec.node, "aa11bb22"); assert_eq!(rec.subnet, "home"); assert_eq!(rec.enrolled_at, 42); @@ -443,7 +453,10 @@ mod tests { assert_eq!(s.merge_record(first.clone()), EnrollMergeOutcome::Inserted); assert_eq!(s.merge_record(first.clone()), EnrollMergeOutcome::Unchanged); let usurper = record("aa11bb22", "home", "ccdd"); - assert_eq!(s.merge_record(usurper), EnrollMergeOutcome::CollisionDropped); + assert_eq!( + s.merge_record(usurper), + EnrollMergeOutcome::CollisionDropped + ); assert_eq!(s.records.len(), 1); assert_eq!(s.find("aa11bb22", "home"), Some(&first), "existing kept"); } @@ -458,7 +471,10 @@ mod tests { use rsa::pkcs8::EncodePublicKey; let key = rsa::RsaPrivateKey::new(&mut rand::thread_rng(), 1024).unwrap(); let der = key.to_public_key().to_public_key_der().unwrap(); - (key, der.as_bytes().iter().map(|b| format!("{b:02x}")).collect()) + ( + key, + der.as_bytes().iter().map(|b| format!("{b:02x}")).collect(), + ) } /// The RETIRED CNG RSAPUBLICBLOB spelling, kept ONLY as the negative @@ -512,7 +528,9 @@ mod tests { ); assert_eq!( verify_backend_signature("libfido2-es256", &spki_hex, &payload, &sig), - Err(SigVerifyRefusal::UnknownBackendKind("libfido2-es256".to_string())) + Err(SigVerifyRefusal::UnknownBackendKind( + "libfido2-es256".to_string() + )) ); assert!(matches!( verify_backend_signature("hello-kcm-rs256", "00ff", &payload, &sig), @@ -525,7 +543,10 @@ mod tests { // A respelled tuple (the exactness rider's shape: same values, // different spelling) diverges the payload bytes and reads invalid. let respelled = crate::seal::fido2_signing_payload("abc", "home:ling@aa11", 0x2A); - assert_eq!(respelled, payload, "same u64 formats identically — the spelling IS the value"); + assert_eq!( + respelled, payload, + "same u64 formats identically — the spelling IS the value" + ); let padded = b"spt-seal-fido2-v1\nabc\nhome:ling@aa11\n042\n"; assert_eq!( verify_backend_signature("hello-kcm-rs256", &spki_hex, padded, &sig), @@ -563,7 +584,10 @@ mod tests { "the fixture really is DER SPKI, not a blob wearing the name: {}", &spki_hex[..8] ); - assert!(retired.starts_with("52534131"), "the control really is an RSAPUBLICBLOB"); + assert!( + retired.starts_with("52534131"), + "the control really is an RSAPUBLICBLOB" + ); assert!( matches!( verify_backend_signature("hello-kcm-rs256", &retired, &payload, &sig), diff --git a/crates/spt-store/src/epoch.rs b/crates/spt-store/src/epoch.rs index 352818e7..671bba21 100644 --- a/crates/spt-store/src/epoch.rs +++ b/crates/spt-store/src/epoch.rs @@ -186,7 +186,10 @@ mod tests { let dir = tempdir().unwrap(); let path = dir.path().join("epoch"); let mut src = EpochSource::load_from(&path); - assert!(src.fast_forward_past(803_460).unwrap(), "a regressed 0 heals"); + assert!( + src.fast_forward_past(803_460).unwrap(), + "a regressed 0 heals" + ); assert_eq!(src.current(), 803_461, "strictly past the fleet's lease"); assert_eq!( EpochSource::load_from(&path).current(), diff --git a/crates/spt-store/src/erole.rs b/crates/spt-store/src/erole.rs index 0629648c..890efd41 100644 --- a/crates/spt-store/src/erole.rs +++ b/crates/spt-store/src/erole.rs @@ -156,9 +156,15 @@ fn fall_through_from(table: &[Surface]) -> String { let mut s = String::from( "A rule covers only the surfaces it lists; unlisted surfaces fall through to the\ntiers below. ", ); - let on: Vec<&str> = table.iter().filter(|s| s.default_on).map(|s| s.id).collect(); + let on: Vec<&str> = table + .iter() + .filter(|s| s.default_on) + .map(|s| s.id) + .collect(); if on.is_empty() { - s.push_str("On by default: none — a blanket closed posture reaches every\nsurface above.\n\n"); + s.push_str( + "On by default: none — a blanket closed posture reaches every\nsurface above.\n\n", + ); } else { s.push_str(&format!( "On by default, and so NOT reached by a blanket closed\nposture: {}. The per-surface verb in tier 4 is the only thing that closes one.\n\n", @@ -241,7 +247,10 @@ mod tests { // nowhere else, so the two renderings cannot drift in content. let rows = surface::control_surface_rows_in(&table); let help = surface::control_surfaces_in(&table); - assert!(role.contains(&rows), "the role joins the composer's rows:\n{role}"); + assert!( + role.contains(&rows), + "the role joins the composer's rows:\n{role}" + ); assert!(help.contains(&rows), "and so does the help:\n{help}"); assert_eq!( help, @@ -267,7 +276,10 @@ mod tests { .filter(|s| s.default_on) .map(|s| s.id) .collect(); - assert!(!named.is_empty(), "the shipped table has a default-on surface"); + assert!( + !named.is_empty(), + "the shipped table has a default-on surface" + ); assert!( live.contains(&format!("posture: {}.", named.join(", "))), "the role names the table's default-on set, joined from the table:\n{live}" diff --git a/crates/spt-store/src/gate.rs b/crates/spt-store/src/gate.rs index 24a13dce..01c80b74 100644 --- a/crates/spt-store/src/gate.rs +++ b/crates/spt-store/src/gate.rs @@ -261,7 +261,8 @@ pub fn access_check_with_sender( _ => Origin::RemoteNode, }; - if let Some(refusal) = engine_room_inbound_refusal(endpoint, origin_node, surface, class, origin) + if let Some(refusal) = + engine_room_inbound_refusal(endpoint, origin_node, surface, class, origin) { return refusal; } @@ -345,7 +346,8 @@ pub fn access_check_with_sender( // same-node operation it always was. Named as such (not as an implicit // open) because the two are different facts and the trust-warning // composer reads the difference. - if matches!(origin, Origin::LocalNode { .. }) && matches!(verdict.tier, MatchedTier::ImplicitOpen) + if matches!(origin, Origin::LocalNode { .. }) + && matches!(verdict.tier, MatchedTier::ImplicitOpen) { return AccessDecision::Allow(PassReason::SameNode); } @@ -434,7 +436,6 @@ pub fn classify_engine_room_inbound( InboundLock::Unsolicited } - /// The I/O half: the lock's verdict for `endpoint`, or `None` when the lock has /// nothing to say. Returns a REFUSAL only — an engine room still passes through /// the ordinary chain, so the lock can never widen access, only narrow it. @@ -526,10 +527,7 @@ fn targets_engine_room(target: &str) -> bool { return true; } let perch = |id: &str| crate::perch::resolve_perch_path(id, crate::perch::ParentHint::Infer); - same_resolved_dir( - &perch(target), - &perch(crate::engineroom::ENGINE_ROOM_ID), - ) + same_resolved_dir(&perch(target), &perch(crate::engineroom::ENGINE_ROOM_ID)) } /// Do two paths name the SAME real directory? The pure half of @@ -548,8 +546,6 @@ fn same_resolved_dir(a: &std::path::Path, b: &std::path::Path) -> bool { } } - - /// Epoch milliseconds — the clock the reply window is measured against. fn now_ms() -> u64 { std::time::SystemTime::now() diff --git a/crates/spt-store/src/home.rs b/crates/spt-store/src/home.rs index 10b602de..946d2de7 100644 --- a/crates/spt-store/src/home.rs +++ b/crates/spt-store/src/home.rs @@ -447,8 +447,15 @@ mod tests { // (1) Incoming BARE parent (ADR-0021 agnostic hook-bind resolution) → KEEP // the prior composite (this used to clobber to `claude-spt` — the bug). let mut r = InfoJson::new("ep", "t2", 2, "sid2", "live_agent"); - stamp_creation_fields(&mut r, Some(&prior), &sole, &mut vis, None, Some("claude-spt")) - .unwrap(); + stamp_creation_fields( + &mut r, + Some(&prior), + &sole, + &mut vis, + None, + Some("claude-spt"), + ) + .unwrap(); assert_eq!( r.adapter.as_deref(), Some("claude-spt:ccs"), @@ -457,15 +464,33 @@ mod tests { // (2) Genuinely different adapter → replaced (resume-under-new). let mut r2 = InfoJson::new("ep", "t2", 2, "sid2", "live_agent"); - stamp_creation_fields(&mut r2, Some(&prior), &sole, &mut vis, None, Some("other-adapter")) - .unwrap(); - assert_eq!(r2.adapter.as_deref(), Some("other-adapter"), "different adapter replaces"); + stamp_creation_fields( + &mut r2, + Some(&prior), + &sole, + &mut vis, + None, + Some("other-adapter"), + ) + .unwrap(); + assert_eq!( + r2.adapter.as_deref(), + Some("other-adapter"), + "different adapter replaces" + ); // (3) A different EXPLICIT profile on the same parent still wins (a real // profile change, NOT the agnostic bare-parent bind). let mut r3 = InfoJson::new("ep", "t2", 2, "sid2", "live_agent"); - stamp_creation_fields(&mut r3, Some(&prior), &sole, &mut vis, None, Some("claude-spt:fast")) - .unwrap(); + stamp_creation_fields( + &mut r3, + Some(&prior), + &sole, + &mut vis, + None, + Some("claude-spt:fast"), + ) + .unwrap(); assert_eq!( r3.adapter.as_deref(), Some("claude-spt:fast"), @@ -475,16 +500,31 @@ mod tests { // (4) No incoming adapter → prior carries forward unchanged. let mut r4 = InfoJson::new("ep", "t2", 2, "sid2", "live_agent"); stamp_creation_fields(&mut r4, Some(&prior), &sole, &mut vis, None, None).unwrap(); - assert_eq!(r4.adapter.as_deref(), Some("claude-spt:ccs"), "no incoming → prior carries"); + assert_eq!( + r4.adapter.as_deref(), + Some("claude-spt:ccs"), + "no incoming → prior carries" + ); // (5) A BARE prior has no profile to protect → the incoming (equal) bare // value is used, unchanged behavior. let mut bare_prior = prior.clone(); bare_prior.adapter = Some("claude-spt".to_string()); let mut r5 = InfoJson::new("ep", "t2", 2, "sid2", "live_agent"); - stamp_creation_fields(&mut r5, Some(&bare_prior), &sole, &mut vis, None, Some("claude-spt")) - .unwrap(); - assert_eq!(r5.adapter.as_deref(), Some("claude-spt"), "bare prior + bare incoming"); + stamp_creation_fields( + &mut r5, + Some(&bare_prior), + &sole, + &mut vis, + None, + Some("claude-spt"), + ) + .unwrap(); + assert_eq!( + r5.adapter.as_deref(), + Some("claude-spt"), + "bare prior + bare incoming" + ); } // [unit->REQ-INST-15] first-join adoption: with exactly one subnet, an diff --git a/crates/spt-store/src/inbound.rs b/crates/spt-store/src/inbound.rs index ed3499af..f2ce08f8 100644 --- a/crates/spt-store/src/inbound.rs +++ b/crates/spt-store/src/inbound.rs @@ -38,7 +38,9 @@ use crate::atomic::atomic_write_string; /// The canonical path: `/identity/inbound.json`. pub fn inbound_file() -> PathBuf { - crate::perch::spt_home().join("identity").join("inbound.json") + crate::perch::spt_home() + .join("identity") + .join("inbound.json") } /// What the binder learned. Every non-`Ok` variant that a renderer should @@ -138,12 +140,7 @@ pub struct InboundRecord { /// must never fail a daemon bringup, so an unwritable home degrades to no /// record, which reads as [`InboundVerdict::Unknown`]. pub fn write(binder_path: &Path, verdict: &InboundVerdict) { - write_to( - &inbound_file(), - std::process::id(), - binder_path, - verdict, - ) + write_to(&inbound_file(), std::process::id(), binder_path, verdict) } /// [`write`] against an explicit path and identity (the seam tests drive). @@ -253,10 +250,7 @@ mod tests { fn a_dead_binder_discards_even_a_green_verdict() { let path = tmp("dead"); write_to(&path, 4242, Path::new(BINDER), &InboundVerdict::Ok); - assert_eq!( - read_current_from(&path, |_| None), - InboundVerdict::Unknown - ); + assert_eq!(read_current_from(&path, |_| None), InboundVerdict::Unknown); } // [unit->REQ-INBOUND-VERDICT-RECORD-BINDER-PINNED] pid reuse: the number is @@ -311,7 +305,10 @@ mod tests { let missing = InboundVerdict::Missing { fix: "netsh add rule FIXLINE".to_string(), }; - assert!(missing.warning().unwrap().contains("netsh add rule FIXLINE")); + assert!(missing + .warning() + .unwrap() + .contains("netsh add rule FIXLINE")); let mismatch = InboundVerdict::PathMismatch { rule_path: r"C:\installed\spt.exe".to_string(), diff --git a/crates/spt-store/src/info.rs b/crates/spt-store/src/info.rs index fef93e30..5732a9b6 100644 --- a/crates/spt-store/src/info.rs +++ b/crates/spt-store/src/info.rs @@ -501,7 +501,10 @@ pub fn mutate_info(perch_path: &Path, mutate: impl FnOnce(&mut InfoJson)) -> std // Hold the stable per-perch sentinel across the whole read→mutate→write RMW. let _lock = lock_perch_sentinel(perch_path)?; let mut rec = read_info(perch_path).ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::NotFound, "info.json absent or unreadable") + std::io::Error::new( + std::io::ErrorKind::NotFound, + "info.json absent or unreadable", + ) })?; mutate(&mut rec); // Already holding the lock — use the UNLOCKED writer (re-locking would deadlock). @@ -833,10 +836,7 @@ pub fn set_psyche_host_error( pub fn set_psyche_role_absent(perch_path: &Path, role: Option<&str>) -> std::io::Result<()> { mutate_info(perch_path, |rec| match role { Some(r) => { - let unchanged = rec - .psyche_role_absent - .as_ref() - .is_some_and(|a| a.role == r); + let unchanged = rec.psyche_role_absent.as_ref().is_some_and(|a| a.role == r); if !unchanged { rec.psyche_role_absent = Some(PsycheRoleAbsent { role: r.to_string(), @@ -1091,7 +1091,13 @@ mod tests { fn anchored_skeleton_never_overwrites_an_existing_record() { let d = perch(); let mut vis = crate::visibility::VisibilityStore::default(); - let mut live = InfoJson::new("engine-room", "2026-08-21T00:00:00Z", 7, "sid-live", "live_agent"); + let mut live = InfoJson::new( + "engine-room", + "2026-08-21T00:00:00Z", + 7, + "sid-live", + "live_agent", + ); live.home_subnet = Some("SPT_MANTLE".to_string()); write_info(d.path(), &live).unwrap(); @@ -1197,7 +1203,9 @@ mod tests { // A stamped value round-trips; absent is omitted on serialize. let mut rec = InfoJson::new("a", "t", 7, "s", "live_agent"); - assert!(!serde_json::to_string(&rec).unwrap().contains("controllable")); + assert!(!serde_json::to_string(&rec) + .unwrap() + .contains("controllable")); rec.controllable = Some(false); write_info(d.path(), &rec).unwrap(); assert_eq!(read_info(d.path()).unwrap().controllable, Some(false)); @@ -1503,10 +1511,16 @@ mod tests { // Verdict against a DIFFERENT pid (the relay re-launched): nothing written. assert!(!converge_dead_relay(d.path(), "sid-1", 9999).unwrap()); - assert_eq!(read_info(d.path()).unwrap().status.as_deref(), Some("online")); + assert_eq!( + read_info(d.path()).unwrap().status.as_deref(), + Some("online") + ); // Verdict against an old session (a newer bind rotated it): nothing written. assert!(!converge_dead_relay(d.path(), "sid-old", 4242).unwrap()); - assert_eq!(read_info(d.path()).unwrap().status.as_deref(), Some("online")); + assert_eq!( + read_info(d.path()).unwrap().status.as_deref(), + Some("online") + ); // The matching pair applies the whole terminal triple in one write. assert!(converge_dead_relay(d.path(), "sid-1", 4242).unwrap()); @@ -1711,15 +1725,24 @@ mod tests { assert_eq!(read_info(d.path()).unwrap().psyche_host_error, None); // First failure → attempts = 1, reason captured, ts present. - set_psyche_host_error(d.path(), Some("psychebin: program not found"), &BTreeMap::new()) - .unwrap(); + set_psyche_host_error( + d.path(), + Some("psychebin: program not found"), + &BTreeMap::new(), + ) + .unwrap(); let e = read_info(d.path()).unwrap().psyche_host_error.unwrap(); assert_eq!(e.attempts, 1); assert_eq!(e.reason, "psychebin: program not found"); - assert!(!e.ts.is_empty() && e.ts.ends_with('Z'), "RFC3339-UTC ts: {}", e.ts); + assert!( + !e.ts.is_empty() && e.ts.ends_with('Z'), + "RFC3339-UTC ts: {}", + e.ts + ); // Retry → OVERWRITES reason + ts, INCREMENTS attempts (current-state, not a log). - set_psyche_host_error(d.path(), Some("psychebin: still missing"), &BTreeMap::new()).unwrap(); + set_psyche_host_error(d.path(), Some("psychebin: still missing"), &BTreeMap::new()) + .unwrap(); let e = read_info(d.path()).unwrap().psyche_host_error.unwrap(); assert_eq!(e.attempts, 2, "attempts increments per retry"); assert_eq!(e.reason, "psychebin: still missing", "reason overwritten"); @@ -1737,17 +1760,28 @@ mod tests { // [unit->REQ-WAKE-RESUME-LEG] set_status(d.path(), crate::liveness::STATUS_ONLINE).unwrap(); let raw = std::fs::read_to_string(d.path().join("info.json")).unwrap(); - assert!(!raw.contains("host_error"), "host_error absent by default: {raw}"); + assert!( + !raw.contains("host_error"), + "host_error absent by default: {raw}" + ); assert_eq!(read_info(d.path()).unwrap().host_error, None); // Stamp a host-level failure report. - set_host_error(d.path(), Some("wake-resume: adapter 'ghost' is not registered")).unwrap(); + set_host_error( + d.path(), + Some("wake-resume: adapter 'ghost' is not registered"), + ) + .unwrap(); let rec = read_info(d.path()).unwrap(); assert_eq!( rec.host_error.as_deref(), Some("wake-resume: adapter 'ghost' is not registered") ); // status UNTOUCHED — host_error is a report, never a liveness input. - assert_eq!(rec.status.as_deref(), Some(crate::liveness::STATUS_ONLINE), "host_error must not touch status"); + assert_eq!( + rec.status.as_deref(), + Some(crate::liveness::STATUS_ONLINE), + "host_error must not touch status" + ); // Overwrite = current-state stamp (not a log). set_host_error(d.path(), Some("wake-resume: adapter 'ghost' still missing")).unwrap(); assert_eq!( @@ -1813,7 +1847,11 @@ mod tests { "an empty latch set emits NO key — pre-#115 bytes: {raw}" ); assert_eq!( - read_info(d.path()).unwrap().psyche_host_error.unwrap().slots, + read_info(d.path()) + .unwrap() + .psyche_host_error + .unwrap() + .slots, BTreeMap::new() ); @@ -1821,10 +1859,17 @@ mod tests { // reason — the composed sentence stays decomposable after a bounce. let slots = BTreeMap::from([ ("ingest".to_string(), "psyche ingest failed 3x".to_string()), - ("timeout".to_string(), "psyche turn timed out 10x".to_string()), + ( + "timeout".to_string(), + "psyche turn timed out 10x".to_string(), + ), ]); - set_psyche_host_error(d.path(), Some("psyche ingest failed 3x | psyche turn timed out 10x"), &slots) - .unwrap(); + set_psyche_host_error( + d.path(), + Some("psyche ingest failed 3x | psyche turn timed out 10x"), + &slots, + ) + .unwrap(); let e = read_info(d.path()).unwrap().psyche_host_error.unwrap(); assert_eq!(e.slots, slots, "slot map round-trips"); assert_eq!( @@ -1847,7 +1892,10 @@ mod tests { let legacy = read_info(old.path()).unwrap().psyche_host_error.unwrap(); assert_eq!(legacy.reason, "boom"); assert_eq!(legacy.attempts, 2); - assert!(legacy.slots.is_empty(), "a slotless stamp reads as no latches"); + assert!( + legacy.slots.is_empty(), + "a slotless stamp reads as no latches" + ); // N-1, OLD binary / NEW record: the struct does not deny unknown fields, so // a key this binary has never heard of parses rather than poisoning the whole @@ -1860,7 +1908,10 @@ mod tests { ) .unwrap(); let fwd = read_info(future.path()).unwrap().psyche_host_error.unwrap(); - assert_eq!(fwd.reason, "boom", "an unknown sibling key does not break the parse"); + assert_eq!( + fwd.reason, "boom", + "an unknown sibling key does not break the parse" + ); assert_eq!(fwd.slots.get("turn").map(String::as_str), Some("x")); } @@ -1901,7 +1952,8 @@ mod tests { // A healthy respawn clears it. set_translation_fault(d.path(), None).unwrap(); assert_eq!( - read_info(d.path()).unwrap().translation_fault, None, + read_info(d.path()).unwrap().translation_fault, + None, "a healthy respawn shows clean" ); @@ -2016,8 +2068,7 @@ mod tests { let b = std::thread::spawn(move || { bb.wait(); // B: bind writes the full record (state=live_agent + controllable=true). - let mut rec = - InfoJson::new("hall-a", "t", std::process::id(), "sid", "live_agent"); + let mut rec = InfoJson::new("hall-a", "t", std::process::id(), "sid", "live_agent"); rec.controllable = Some(true); write_info(&pb, &rec).unwrap(); }); diff --git a/crates/spt-store/src/iolog.rs b/crates/spt-store/src/iolog.rs index 15e56735..58819990 100644 --- a/crates/spt-store/src/iolog.rs +++ b/crates/spt-store/src/iolog.rs @@ -141,6 +141,14 @@ pub struct IoLogRow { pub mid: bool, } +/// A poll's selected rows and the global prefix maximum from the same snapshot. +#[derive(Debug, Default)] +pub struct IoLogRead { + pub rows: Vec, + /// Independent of the cursor, output limit, and whether row JSON parses. + pub head: u64, +} + /// The log file for an already-resolved perch. // [impl->REQ-HAZARD-SINGLE-PATH-SOURCE] pub fn io_log_file_at(perch_path: &Path) -> PathBuf { @@ -190,12 +198,13 @@ fn line_seq(line: &str) -> Option { /// rather than answering wrong. const TAIL_WINDOW: u64 = 256 * 1024; -/// The highest seq the log holds, or 0 when it holds nothing. +/// The highest seq in the complete rows of the tail window, or 0 if empty. /// -/// **Read from the tail, not by counting**: this runs on every append, and a -/// whole-file read per append would make the log's cost quadratic in its own -/// length. +/// Healthy logs are increasing, so this is their head. Append integrity and +/// poll snapshots scan all prefixes instead: a damaged log's older maximum can +/// lie outside this window. // [impl->REQ-IO-EVENT-ADAPTER-LOG] +// [impl->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] pub fn last_seq_at(perch_path: &Path) -> u64 { let path = io_log_file_at(perch_path); let Ok(mut f) = std::fs::File::open(&path) else { @@ -211,41 +220,91 @@ pub fn last_seq_at(perch_path: &Path) -> u64 { if f.seek(SeekFrom::Start(start)).is_err() { return 0; } - let mut buf = String::new(); - if f.read_to_string(&mut buf).is_err() { + let mut buf = Vec::new(); + if f.read_to_end(&mut buf).is_err() { return 0; } - // A window that reached no line start at all fell short of even ONE row; - // re-read whole rather than answer from a fragment. - if start > 0 && !buf.contains('\n') { - return std::fs::read_to_string(&path) - .ok() - .and_then(|s| s.lines().rev().find_map(line_seq)) - .unwrap_or(0); - } - let mut lines: Vec<&str> = buf.lines().collect(); - if start > 0 && !lines.is_empty() { - // The first line in a mid-file window is a fragment of an earlier row. - lines.remove(0); - } - lines.iter().rev().find_map(|l| line_seq(l)).unwrap_or(0) -} - -/// The lowest seq the log holds, or 0 when it holds nothing. Read from the head, -/// for the same reason [`last_seq_at`] reads from the tail. -fn first_seq_at(perch_path: &Path) -> u64 { - let Ok(mut f) = std::fs::File::open(io_log_file_at(perch_path)) else { - return 0; + let complete = if start > 0 { + // Drop the fragment BEFORE decoding: the seek can bisect a codepoint. + match buf.iter().position(|&b| b == b'\n') { + Some(end) if end + 1 < buf.len() => &buf[end + 1..], + _ => { + // No complete row remains, including a window ending at the + // only row's newline. Read whole rather than answer falsely 0. + return std::fs::read(&path) + .ok() + .map(|bytes| { + String::from_utf8_lossy(&bytes) + .lines() + .filter_map(line_seq) + .max() + .unwrap_or(0) + }) + .unwrap_or(0); + } + } + } else { + &buf[..] }; - let mut buf = vec![0u8; TAIL_WINDOW as usize]; - let Ok(n) = f.read(&mut buf) else { return 0 }; - buf.truncate(n); - String::from_utf8_lossy(&buf) + String::from_utf8_lossy(complete) .lines() - .find_map(line_seq) + .filter_map(line_seq) + .max() .unwrap_or(0) } +/// Read only the ASCII sequence prefix; payload bytes need not decode. +fn byte_line_seq(line: &[u8]) -> Option { + let tab = line.iter().position(|&b| b == b'\t')?; + std::str::from_utf8(&line[..tab]).ok()?.trim().parse().ok() +} + +/// One full read supplies integrity, global maximum, retention count, and any +/// rewrite bytes. Healthy logs are bounded to 1250 payload-capped rows (on-disk +/// bytes include JSON escaping); legacy oversized logs pay their full scan +/// until repaired. Healthy appends scan but do not rewrite the file. +/// Endpoints alone cannot prove integrity: 1, 2, 1, 3 has increasing endpoints. +// [impl->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] +struct LogScan { + body: Vec, + rows: usize, + head: u64, + damaged: bool, +} + +impl LogScan { + fn read(path: &Path) -> io::Result { + let body = match std::fs::read(path) { + Ok(body) => body, + Err(e) if e.kind() == io::ErrorKind::NotFound => Vec::new(), + Err(e) => return Err(e), + }; + let mut rows = 0; + let mut head = 0; + let mut previous = None; + let mut damaged = false; + for line in body.split_inclusive(|&b| b == b'\n') { + rows += 1; + if let Some(seq) = byte_line_seq(line) { + damaged |= previous.is_some_and(|prev| seq <= prev); + previous = Some(seq); + head = head.max(seq); + } + } + Ok(Self { + body, + rows, + head, + damaged, + }) + } +} + +fn next_seq(seq: u64) -> io::Result { + seq.checked_add(1) + .ok_or_else(|| io::Error::other("io-events sequence exhausted")) +} + /// Append one event, assigning it the next seq. Answers the seq assigned. /// /// **Serialized under an exclusive advisory lock.** The daemon publishes from @@ -266,46 +325,92 @@ pub fn append_at(perch_path: &Path, row: &IoLogRow) -> io::Result { result } +// [impl->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] +// [impl->REQ-IO-EVENT-ADAPTER-LOG] fn append_locked(perch_path: &Path, row: &IoLogRow) -> io::Result { - let seq = last_seq_at(perch_path).saturating_add(1); + let path = io_log_file_at(perch_path); + let mut scan = LogScan::read(&path)?; + let mut repaired = None; + if scan.damaged { + // Repair only retained history, in file order, above EVERY old prefix. + // Old cursors see this history once; normal positional retention bounds + // that replay. Never deserialize/reserialize the JSON half. + let keep = retained_rows(scan.rows); + let offset = scan + .body + .split_inclusive(|&b| b == b'\n') + .take(scan.rows - keep) + .map(<[u8]>::len) + .sum::(); + let retained = &scan.body[offset..]; + let mut body = Vec::with_capacity(retained.len()); + for line in retained.split_inclusive(|&b| b == b'\n') { + if byte_line_seq(line).is_some() { + scan.head = next_seq(scan.head)?; + let tab = line.iter().position(|&b| b == b'\t').unwrap(); + write!(&mut body, "{}", scan.head)?; + body.extend_from_slice(&line[tab..]); + } else { + // Corrupt unkeyed lines remain unreadable, but are not lost. + body.extend_from_slice(line); + } + } + scan.rows = keep; + repaired = Some(body); + } + // Preflight the entire repair AND new row before mutating the file: neither + // saturation nor a partially committed repair may consume the last cursor. + let seq = next_seq(scan.head)?; let mut stamped = row.clone(); stamped.seq = seq; let line = compose_line(&stamped).map_err(io::Error::other)?; + if let Some(body) = repaired { + crate::atomic::atomic_write_bytes(&path, &body)?; + scan.body = body; + } let mut f = std::fs::OpenOptions::new() .create(true) .append(true) - .open(io_log_file_at(perch_path))?; + .open(&path)?; f.write_all(line.as_bytes())?; - // The trim is best-effort ON PURPOSE: a retention sweep that fails must not - // cost the caller the event it just recorded. An over-long log is a disk - // cost; a lost event is a hole in the record an adapter cannot detect. - let _ = trim_locked(perch_path, seq); + drop(f); + // Retention remains best-effort after the event is safely appended. Reuse + // the scan bytes rather than reading the entire file again for a trim. + scan.rows += 1; + if retained_rows(scan.rows) < scan.rows { + scan.body.extend_from_slice(line.as_bytes()); + let _ = trim_locked(perch_path, &scan.body, scan.rows); + } Ok(seq) } /// Drop the oldest rows when the log has run past its bound plus slack. /// -/// Seqs are contiguous — assigned +1 per append and trimmed only from the front -/// — so the row count is `last - first + 1` and needs no scan to compute. +/// Count physical lines, not sequence distance; reset blocks need exactly the +/// same newest-N retention as healthy logs. // [impl->REQ-IO-EVENT-ADAPTER-LOG] -fn trim_locked(perch_path: &Path, last: u64) -> io::Result<()> { - let first = first_seq_at(perch_path); - if first == 0 { - return Ok(()); +// [impl->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] +fn retained_rows(rows: usize) -> usize { + if rows as u64 > IO_LOG_MAX_ROWS + IO_LOG_TRIM_SLACK { + IO_LOG_MAX_ROWS as usize + } else { + rows } - let rows = last.saturating_sub(first).saturating_add(1); - if rows <= IO_LOG_MAX_ROWS + IO_LOG_TRIM_SLACK { +} + +// [impl->REQ-IO-EVENT-ADAPTER-LOG] +// [impl->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] +fn trim_locked(perch_path: &Path, body: &[u8], rows: usize) -> io::Result<()> { + let drop = rows - retained_rows(rows); + if drop == 0 { return Ok(()); } - let keep_from = last.saturating_sub(IO_LOG_MAX_ROWS - 1); - let path = io_log_file_at(perch_path); - let body = std::fs::read_to_string(&path)?; - let kept: String = body - .lines() - .filter(|l| line_seq(l).is_some_and(|s| s >= keep_from)) - .map(|l| format!("{l}\n")) - .collect(); - crate::atomic::atomic_write_string(&path, &kept).map_err(io::Error::other) + let offset = body + .split_inclusive(|&b| b == b'\n') + .take(drop) + .map(<[u8]>::len) + .sum::(); + crate::atomic::atomic_write_bytes(&io_log_file_at(perch_path), &body[offset..]) } /// Every row with `seq` strictly greater than `after`, oldest first. @@ -316,7 +421,8 @@ fn trim_locked(perch_path: &Path, last: u64) -> io::Result<()> { /// **Takes the SHARED lock**: a trim rewrites the file, and a reader that raced /// it would see a half-written log. Readers do not exclude each other. // [impl->REQ-IO-EVENT-ADAPTER-LOG] -pub fn read_after_at(perch_path: &Path, after: u64, limit: Option) -> Vec { +// [impl->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] +pub fn read_after_at(perch_path: &Path, after: u64, limit: Option) -> IoLogRead { let lock = std::fs::OpenOptions::new() .create(true) .write(true) @@ -326,23 +432,23 @@ pub fn read_after_at(perch_path: &Path, after: u64, limit: Option) -> Vec if let Some(l) = lock.as_ref() { let _ = l.lock_shared(); } - let body = std::fs::read_to_string(io_log_file_at(perch_path)).unwrap_or_default(); + let body = std::fs::read(io_log_file_at(perch_path)).unwrap_or_default(); if let Some(l) = lock.as_ref() { let _ = FileExt::unlock(l); } - let mut out: Vec = Vec::new(); - for line in body.lines() { - // The cheap prefix test FIRST: an already-seen row costs an integer - // parse, never a JSON one. - match line_seq(line) { - Some(s) if s > after => {} - _ => continue, - } - if let Some(row) = parse_line(line) { - out.push(row); + let mut out = IoLogRead::default(); + for line in body.split_inclusive(|&b| b == b'\n') { + // Keep scanning prefixes after the limit: head belongs to this entire + // shared-lock snapshot, not the last delivered (or decodable) row. + let Some(seq) = byte_line_seq(line) else { + continue; + }; + out.head = out.head.max(seq); + if seq <= after || limit.is_some_and(|n| out.rows.len() >= n) { + continue; } - if limit.is_some_and(|n| out.len() >= n) { - break; + if let Some(row) = std::str::from_utf8(line).ok().and_then(parse_line) { + out.rows.push(row); } } out @@ -418,6 +524,280 @@ mod tests { p } + fn fixture(seqs: impl IntoIterator) -> Vec { + let mut body = Vec::new(); + for (position, seq) in seqs.into_iter().enumerate() { + // Deliberately noncanonical JSON, including an unknown field and + // escape spellings: repair must preserve bytes, not just meaning. + writeln!( + &mut body, + "{seq}\t{{ \"payload\": \"p{}\\u4e16\", \"kind\": \"MSG_IN\", \"at_ms\": 1, \"future\": true }}", + position + 1 + ) + .unwrap(); + } + body + } + + fn payload_bytes(body: &[u8]) -> Vec<&[u8]> { + body.split_inclusive(|&b| b == b'\n') + .map(|line| &line[line.iter().position(|&b| b == b'\t').unwrap() + 1..]) + .collect() + } + + // [unit->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] + #[test] + fn a_tail_window_inside_three_byte_utf8_never_resets_the_seq() { + let d = tmp("utf8-window"); + let mut body = Vec::new(); + let last = 32; + let mut event = row("AGENT_OUTPUT", &"\u{4e16}".repeat(4_000)); + for seq in 1..=last { + event.seq = seq; + body.extend_from_slice(compose_line(&event).unwrap().as_bytes()); + } + // Adjust only trailing JSON whitespace until the fixed window bisects + // 世. Rows use literal LF on every OS; no text-mode CRLF translation. + for _ in 0..3 { + let start = body.len() - TAIL_WINDOW as usize; + if (0x80..=0xbf).contains(&body[start]) { + break; + } + body.insert(body.len() - 1, b' '); + } + let start = body.len() - TAIL_WINDOW as usize; + assert!( + (0x80..=0xbf).contains(&body[start]), + "window begins at a continuation byte" + ); + let lead = if body[start - 1] == 0xe4 { + start - 1 + } else { + start - 2 + }; + assert_eq!(&body[lead..lead + 3], "\u{4e16}".as_bytes()); + std::fs::write(io_log_file_at(&d), body).unwrap(); + // Mutation-sensitive even though append's independent integrity scan + // can mask last_seq_at regressing to read_to_string/InvalidData -> 0. + assert_eq!(last_seq_at(&d), last); + assert_eq!(append_at(&d, &row("USER_INPUT", "next")).unwrap(), last + 1); + } + + // [unit->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] + #[test] + fn a_tail_without_a_complete_row_falls_back_to_the_whole_file() { + for terminated in [false, true] { + let d = tmp(if terminated { + "giant-lf" + } else { + "giant-no-lf" + }); + let mut event = row("AGENT_OUTPUT", &"x".repeat(TAIL_WINDOW as usize + 100)); + event.seq = 87; + let mut body = compose_line(&event).unwrap(); + if !terminated { + body.pop(); + } + std::fs::write(io_log_file_at(&d), body).unwrap(); + assert_eq!(last_seq_at(&d), 87, "terminated={terminated}"); + } + } + + // [unit->REQ-IO-EVENT-ADAPTER-LOG] + // [unit->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] + #[test] + fn reset_blocks_repair_above_the_max_without_changing_payload_bytes() { + let d = tmp("repair-blocks"); + let body = fixture([201, 202, 203, 1, 2, 3]); + std::fs::write(io_log_file_at(&d), &body).unwrap(); + assert_eq!(last_seq_at(&d), 203, "tail maximum, not its last line"); + assert_eq!(append_at(&d, &row("USER_INPUT", "new")).unwrap(), 210); + let repaired = std::fs::read(io_log_file_at(&d)).unwrap(); + assert_eq!(&payload_bytes(&repaired)[..6], payload_bytes(&body)); + let read = read_after_at(&d, 203, None); + assert_eq!( + read.rows.iter().map(|r| r.seq).collect::>(), + (204..=210).collect::>() + ); + assert_eq!(read.rows.last().unwrap().payload, "new"); + // The next append must not repair already-renumbered history again. + assert_eq!(append_at(&d, &row("USER_INPUT", "later")).unwrap(), 211); + let later = std::fs::read(io_log_file_at(&d)).unwrap(); + assert!(later.starts_with(&repaired)); + } + + // [unit->REQ-IO-EVENT-ADAPTER-LOG] + // [unit->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] + #[test] + fn equal_adjacent_seqs_are_repaired() { + let d = tmp("repair-equal"); + std::fs::write(io_log_file_at(&d), fixture([1, 1])).unwrap(); + assert_eq!(append_at(&d, &row("USER_INPUT", "new")).unwrap(), 4); + let read = read_after_at(&d, 1, None); + assert_eq!( + read.rows.iter().map(|r| r.seq).collect::>(), + vec![2, 3, 4] + ); + } + + // [unit->REQ-IO-EVENT-ADAPTER-LOG] + // [unit->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] + #[test] + fn an_internal_reset_is_repaired_even_when_last_exceeds_first() { + let d = tmp("repair-internal"); + std::fs::write(io_log_file_at(&d), fixture([1, 2, 1, 3])).unwrap(); + assert_eq!(append_at(&d, &row("USER_INPUT", "new")).unwrap(), 8); + let read = read_after_at(&d, 3, None); + assert_eq!( + read.rows.iter().map(|r| r.seq).collect::>(), + (4..=8).collect::>() + ); + } + + // [unit->REQ-IO-EVENT-ADAPTER-LOG] + // [unit->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] + #[test] + fn repair_uses_the_global_max_even_when_it_is_outside_the_tail() { + let d = tmp("repair-global"); + let mut body = fixture([9_000]); + let first_len = body.len(); + let mut event = row("AGENT_OUTPUT", &"\u{4e16}".repeat(4_000)); + for seq in 1..=30 { + event.seq = seq; + body.extend_from_slice(compose_line(&event).unwrap().as_bytes()); + } + assert!(body.len() - TAIL_WINDOW as usize > first_len); + std::fs::write(io_log_file_at(&d), &body).unwrap(); + assert_eq!( + last_seq_at(&d), + 30, + "the older maximum is outside the window" + ); + assert_eq!(append_at(&d, &row("USER_INPUT", "new")).unwrap(), 9_032); + let repaired = std::fs::read(io_log_file_at(&d)).unwrap(); + assert_eq!(&payload_bytes(&repaired)[..31], payload_bytes(&body)); + let read = read_after_at(&d, 9_000, None); + assert_eq!( + read.rows.iter().map(|r| r.seq).collect::>(), + (9_001..=9_032).collect::>() + ); + } + + // [unit->REQ-IO-EVENT-ADAPTER-LOG] + // [unit->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] + #[test] + fn trimming_1251_reset_rows_keeps_the_newest_1000_by_position() { + let d = tmp("trim-reset-position"); + let body = fixture((1..=250).chain(1..=1_000).chain([2_000])); + let lines: Vec<_> = body.split_inclusive(|&b| b == b'\n').collect(); + assert_eq!(lines.len(), 1_251); + let expected = lines[251..].concat(); + // Negative control: last-N by seq value drops 999 newest rows here. + let value_filtered = lines + .iter() + .filter(|line| byte_line_seq(line).is_some_and(|seq| seq >= 1_001)) + .copied() + .collect::>() + .concat(); + assert_ne!(value_filtered, expected); + std::fs::write(io_log_file_at(&d), &body).unwrap(); + trim_locked(&d, &body, lines.len()).unwrap(); + assert_eq!(std::fs::read(io_log_file_at(&d)).unwrap(), expected); + let read = read_after_at(&d, 0, None); + assert_eq!(read.rows.first().unwrap().payload, "p252世"); + assert_eq!(read.rows.last().unwrap().payload, "p1251世"); + assert_eq!(read.rows.len(), IO_LOG_MAX_ROWS as usize); + } + + // [unit->REQ-IO-EVENT-ADAPTER-LOG] + // [unit->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] + #[test] + fn oversized_repair_retains_bounded_newest_history() { + let d = tmp("repair-bounded"); + // The old global maximum is also OUTSIDE the retained suffix. + let body = fixture([9_000].into_iter().chain(1..=1_299)); + std::fs::write(io_log_file_at(&d), &body).unwrap(); + assert_eq!(append_at(&d, &row("USER_INPUT", "new")).unwrap(), 10_001); + let repaired = std::fs::read(io_log_file_at(&d)).unwrap(); + assert_eq!( + &payload_bytes(&repaired)[..1_000], + &payload_bytes(&body)[300..] + ); + let read = read_after_at(&d, 9_000, None); + assert_eq!(read.rows.len(), 1_001); + assert_eq!(read.rows.first().unwrap().seq, 9_001); + assert_eq!(read.rows.last().unwrap().seq, 10_001); + } + + // [unit->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] + #[test] + fn sequence_exhaustion_refuses_without_modifying_history() { + // Healthy exhaustion, repair exhaustion midway, and enough room for + // repair but not its new row must ALL refuse before touching the file. + for (name, seqs) in [ + ("exhausted-healthy", vec![u64::MAX]), + ("exhausted-repair", vec![u64::MAX - 1, 1]), + ("exhausted-new-row", vec![u64::MAX - 2, 1]), + ] { + let d = tmp(name); + let body = fixture(seqs); + std::fs::write(io_log_file_at(&d), &body).unwrap(); + assert!(append_at(&d, &row("USER_INPUT", "new")).is_err()); + assert_eq!(std::fs::read(io_log_file_at(&d)).unwrap(), body); + } + let d = tmp("last-available-seq"); + std::fs::write(io_log_file_at(&d), fixture([u64::MAX - 1])).unwrap(); + assert_eq!(append_at(&d, &row("USER_INPUT", "last")).unwrap(), u64::MAX); + let body = std::fs::read(io_log_file_at(&d)).unwrap(); + assert!(append_at(&d, &row("USER_INPUT", "overflow")).is_err()); + assert_eq!(std::fs::read(io_log_file_at(&d)).unwrap(), body); + } + + // [unit->REQ-IO-EVENT-ADAPTER-LOG] + // [unit->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] + #[test] + fn healthy_sequence_gaps_do_not_trigger_repair_or_retention() { + let d = tmp("healthy-gaps"); + let body = fixture([1, 5_000]); + std::fs::write(io_log_file_at(&d), &body).unwrap(); + assert_eq!(append_at(&d, &row("USER_INPUT", "new")).unwrap(), 5_001); + assert!(std::fs::read(io_log_file_at(&d)) + .unwrap() + .starts_with(&body)); + let read = read_after_at(&d, 0, None); + assert_eq!( + read.rows.iter().map(|r| r.seq).collect::>(), + vec![1, 5_000, 5_001] + ); + } + + // [unit->REQ-IO-EVENT-ADAPTER-LOG] + // [unit->REQ-HAZARD-IOLOG-SEQ-MONOTONIC] + #[test] + fn a_poll_reports_the_true_snapshot_head_independent_of_selected_rows() { + let d = tmp("snapshot-head"); + let mut body = fixture([201, 202, 1, 2]); + body.extend_from_slice(b"203\tnot json\n"); + std::fs::write(io_log_file_at(&d), body).unwrap(); + let capped = read_after_at(&d, 0, Some(1)); + assert_eq!( + capped.rows.iter().map(|r| r.seq).collect::>(), + vec![201] + ); + assert_eq!(capped.head, 203, "scan past the cap and corrupt JSON"); + let uncapped = read_after_at(&d, 201, None); + assert_eq!( + uncapped.rows.iter().map(|r| r.seq).collect::>(), + vec![202] + ); + assert_eq!(uncapped.head, 203); + for (after, limit) in [(202, None), (203, None), (900, None), (0, Some(0))] { + let read = read_after_at(&d, after, limit); + assert!(read.rows.is_empty()); + assert_eq!(read.head, 203, "after={after}, limit={limit:?}"); + } + } + // [unit->REQ-IO-EVENT-ADAPTER-LOG] appends assign a contiguous, monotonic // seq from 1, and a read with no cursor returns them oldest-first. #[test] @@ -426,7 +806,7 @@ mod tests { assert_eq!(append_at(&d, &row("USER_INPUT", "a")).unwrap(), 1); assert_eq!(append_at(&d, &row("AGENT_OUTPUT", "b")).unwrap(), 2); assert_eq!(append_at(&d, &row("MSG_IN", "c")).unwrap(), 3); - let all = read_after_at(&d, 0, None); + let all = read_after_at(&d, 0, None).rows; assert_eq!(all.iter().map(|r| r.seq).collect::>(), vec![1, 2, 3]); assert_eq!( all.iter().map(|r| r.payload.as_str()).collect::>(), @@ -446,15 +826,18 @@ mod tests { for p in ["a", "b", "c", "d"] { append_at(&d, &row("USER_INPUT", p)).unwrap(); } - let after2 = read_after_at(&d, 2, None); + let after2 = read_after_at(&d, 2, None).rows; assert_eq!(after2.iter().map(|r| r.seq).collect::>(), vec![3, 4]); assert!( - read_after_at(&d, 4, None).is_empty(), + read_after_at(&d, 4, None).rows.is_empty(), "a cursor at the head sees nothing" ); - let capped = read_after_at(&d, 0, Some(2)); + let capped = read_after_at(&d, 0, Some(2)).rows; assert_eq!(capped.len(), 2, "limit bounds the answer"); - assert_eq!(capped[0].seq, 1, "and keeps the OLDEST new rows, so no row is skipped"); + assert_eq!( + capped[0].seq, 1, + "and keeps the OLDEST new rows, so no row is skipped" + ); } // [unit->REQ-IO-EVENT-ADAPTER-LOG] a payload full of newlines is ONE row. @@ -466,7 +849,7 @@ mod tests { let body = "line one\nline two\ttabbed\nline three"; append_at(&d, &row("AGENT_OUTPUT", body)).unwrap(); append_at(&d, &row("USER_INPUT", "next")).unwrap(); - let all = read_after_at(&d, 0, None); + let all = read_after_at(&d, 0, None).rows; assert_eq!(all.len(), 2, "the newlines did not mint extra rows"); assert_eq!(all[0].payload, body, "and the body round-trips verbatim"); assert_eq!(all[1].seq, 2); @@ -482,7 +865,7 @@ mod tests { r.truncated = true; let assigned = append_at(&d, &r).unwrap(); assert_eq!(assigned, 1); - let back = read_after_at(&d, 0, None); + let back = read_after_at(&d, 0, None).rows; assert_eq!(back[0].seq, 1, "the LINE key is the log's own cursor"); assert_eq!( back[0].digest_seq, @@ -518,19 +901,23 @@ mod tests { for i in 1..=brim { append_at(&d, &row("USER_INPUT", &format!("p{i}"))).unwrap(); } - let at_brim = read_after_at(&d, 0, None); + let at_brim = read_after_at(&d, 0, None).rows; assert_eq!( at_brim.len() as u64, brim, "the slack is REAL — the log runs past the bound before it rewrites" ); - assert_eq!(at_brim.first().unwrap().seq, 1, "and the first row is still row 1"); + assert_eq!( + at_brim.first().unwrap().seq, + 1, + "and the first row is still row 1" + ); // ── Half two: ONE more append crosses it, and the trim lands on the // BOUND rather than merely back under the slack. let total = brim + 1; append_at(&d, &row("USER_INPUT", &format!("p{total}"))).unwrap(); - let all = read_after_at(&d, 0, None); + let all = read_after_at(&d, 0, None).rows; assert_eq!( all.len() as u64, IO_LOG_MAX_ROWS, @@ -544,7 +931,7 @@ mod tests { ); assert_eq!(last_seq_at(&d), total, "seqs never rewind over a trim"); assert_eq!( - read_after_at(&d, 1, None).len() as u64, + read_after_at(&d, 1, None).rows.len() as u64, IO_LOG_MAX_ROWS, "a cursor into the DROPPED region still sees everything that survives" ); @@ -555,7 +942,7 @@ mod tests { append_at(&d, &row("USER_INPUT", &format!("q{i}"))).unwrap(); } assert!( - (read_after_at(&d, 0, None).len() as u64) <= brim, + (read_after_at(&d, 0, None).rows.len() as u64) <= brim, "the retention ceiling holds across the slack cycle" ); } @@ -573,7 +960,7 @@ mod tests { std::fs::write(&path, &body).unwrap(); let seq = append_at(&d, &row("USER_INPUT", "after")).unwrap(); assert_eq!(seq, 3, "the seq walk read the PREFIX, which was intact"); - let rows = read_after_at(&d, 0, None); + let rows = read_after_at(&d, 0, None).rows; assert_eq!(rows.iter().map(|r| r.seq).collect::>(), vec![1, 3]); } } diff --git a/crates/spt-store/src/knock.rs b/crates/spt-store/src/knock.rs index 4a929104..160c9cba 100644 --- a/crates/spt-store/src/knock.rs +++ b/crates/spt-store/src/knock.rs @@ -665,13 +665,13 @@ pub fn redemption_grant(code: &KnockCode, redeemer: &Redeemer) -> RedemptionGran if !attributable.is_empty() { let (subject, origin) = match redeemer { - Redeemer::Endpoint { id, .. } => { - (Subject::SenderEndpoint { id: id.clone() }, OriginQualifier::Any) - } - Redeemer::User { node } => ( - Subject::Node { node: node.clone() }, - OriginQualifier::User, + Redeemer::Endpoint { id, .. } => ( + Subject::SenderEndpoint { id: id.clone() }, + OriginQualifier::Any, ), + Redeemer::User { node } => { + (Subject::Node { node: node.clone() }, OriginQualifier::User) + } }; rules.push(RedemptionRule { subject, @@ -767,7 +767,11 @@ impl ApproveOutcome { /// three arms are mutually exclusive by construction rather than by the /// caller remembering to check in the right order. // [impl->REQ-KNOCK-AUTHORITY-SPLIT] - pub fn classify(granted: Vec, refused: Vec, answerable_by: &str) -> ApproveOutcome { + pub fn classify( + granted: Vec, + refused: Vec, + answerable_by: &str, + ) -> ApproveOutcome { match (granted.is_empty(), refused.is_empty()) { (false, true) => ApproveOutcome::Approved { granted }, (false, false) => ApproveOutcome::Partial { @@ -1280,7 +1284,11 @@ impl KnockStore { } /// The pending, unexpired knocks addressed to `target`. - pub fn pending_for<'a>(&'a self, target: &'a str, now_ms: u64) -> impl Iterator { + pub fn pending_for<'a>( + &'a self, + target: &'a str, + now_ms: u64, + ) -> impl Iterator { self.knocks.iter().filter(move |k| { k.target == target && k.state == KnockState::Pending @@ -1380,11 +1388,9 @@ impl KnockStore { /// destroy the first and one side of an agreed two-way would simply vanish. // [impl->REQ-HAZARD-MUTUAL-PREAUTH-SIBLING] pub fn arm_mutual(&mut self, pre: MutualPreAuth) { - match self - .pre_auths - .iter_mut() - .find(|p| p.kind == pre.kind && p.key_id == pre.key_id && p.owner == pre.owner && !p.consumed) - { + match self.pre_auths.iter_mut().find(|p| { + p.kind == pre.kind && p.key_id == pre.key_id && p.owner == pre.owner && !p.consumed + }) { Some(slot) => *slot = pre, None => self.pre_auths.push(pre), } @@ -1703,11 +1709,21 @@ mod tests { let far = mine.clone().routed_to("node-b"); assert!(far.outbound, "still ours"); - assert_eq!(far.target_node.as_deref(), Some("node-b"), "and it names where it went"); - assert!(far.sent_to_another_node(), "which is what takes it out of the answer seams"); + assert_eq!( + far.target_node.as_deref(), + Some("node-b"), + "and it names where it went" + ); + assert!( + far.sent_to_another_node(), + "which is what takes it out of the answer seams" + ); let arrived = knock_at("stranger", "me", 1_000); - assert!(!arrived.outbound, "a knock off the wire is not ours to have sent"); + assert!( + !arrived.outbound, + "a knock off the wire is not ours to have sent" + ); assert!(!arrived.sent_to_another_node()); } @@ -1737,11 +1753,15 @@ mod tests { "the knocker we owe the answer to is the one who sent it" ); assert!( - store.answered_outbound("k-nope", "ling", "node-b").is_none(), + store + .answered_outbound("k-nope", "ling", "node-b") + .is_none(), "an unknown correlation id matches nothing" ); assert!( - store.answered_outbound(&id, "someone-else", "node-b").is_none(), + store + .answered_outbound(&id, "someone-else", "node-b") + .is_none(), "an answerer we never knocked is answering a knock that was not made" ); assert!( @@ -1770,7 +1790,10 @@ mod tests { store.upsert(a); store.upsert(b); - assert!(store.record_receipt(&a_id, 4_242), "the named row is stamped"); + assert!( + store.record_receipt(&a_id, 4_242), + "the named row is stamped" + ); assert!( !store.record_receipt("k-never-existed", 4_242), "and an id no row carries stamps nothing" @@ -1779,7 +1802,10 @@ mod tests { let stamped = store.knocks.iter().find(|k| k.id == a_id).expect("row a"); let untouched = store.knocks.iter().find(|k| k.id == b_id).expect("row b"); assert_eq!(stamped.receipt_ms, Some(4_242)); - assert_eq!(untouched.receipt_ms, None, "the receipt did not spill onto its neighbour"); + assert_eq!( + untouched.receipt_ms, None, + "the receipt did not spill onto its neighbour" + ); } // [unit->REQ-UNLISTED-EVIDENCE] a knock we sent to ANOTHER node is RETAINED @@ -1799,13 +1825,32 @@ mod tests { store.upsert(ours); store.upsert(theirs); - assert_eq!(store.knocks.len(), 2, "both rows are kept: {:?}", store.knocks); + assert_eq!( + store.knocks.len(), + 2, + "both rows are kept: {:?}", + store.knocks + ); - let pending: Vec<&str> = store.pending_for("peer", 1_000).map(|k| k.id.as_str()).collect(); - assert_eq!(pending, vec![theirs_id.as_str()], "only the knock ADDRESSED here is pending for it"); + let pending: Vec<&str> = store + .pending_for("peer", 1_000) + .map(|k| k.id.as_str()) + .collect(); + assert_eq!( + pending, + vec![theirs_id.as_str()], + "only the knock ADDRESSED here is pending for it" + ); - let inbox: Vec<&str> = store.inbox_for("peer", false, 1_000).map(|k| k.id.as_str()).collect(); - assert_eq!(inbox, vec![theirs_id.as_str()], "our own outbound row is not an inbox item"); + let inbox: Vec<&str> = store + .inbox_for("peer", false, 1_000) + .map(|k| k.id.as_str()) + .collect(); + assert_eq!( + inbox, + vec![theirs_id.as_str()], + "our own outbound row is not an inbox item" + ); assert!( store.answerable(&ours_id, 1_000).is_none(), @@ -1832,7 +1877,12 @@ mod tests { let replaced = store.upsert(sent_to("me", "you", "node-b", 2_000)); assert!(replaced, "a re-send refreshes our own row"); - assert_eq!(store.knocks.len(), 2, "and does not queue a third: {:?}", store.knocks); + assert_eq!( + store.knocks.len(), + 2, + "and does not queue a third: {:?}", + store.knocks + ); assert_eq!( store.knocks.iter().filter(|k| k.outbound).count(), 1, @@ -1850,7 +1900,10 @@ mod tests { "tier":"endpoint","surfaces":["MSG"],"created_ms":1,"expires_ms":2, "state":"pending"}"#; let parsed: Knock = serde_json::from_str(old).unwrap(); - assert!(!parsed.outbound, "a pre-field row is not read as one we sent"); + assert!( + !parsed.outbound, + "a pre-field row is not read as one we sent" + ); assert_eq!(parsed.target_node, None); assert_eq!(parsed.receipt_ms, None); assert!( @@ -1860,7 +1913,10 @@ mod tests { let bytes = serde_json::to_string(&parsed).unwrap(); for key in ["outbound", "target_node", "receipt_ms"] { - assert!(!bytes.contains(key), "an absent field stays absent: {bytes}"); + assert!( + !bytes.contains(key), + "an absent field stays absent: {bytes}" + ); } let mut with = parsed.clone(); @@ -1896,7 +1952,8 @@ mod tests { owner: "doyle".to_string(), text: "redeemed my invite".to_string(), }); - let round: KnockCode = serde_json::from_str(&serde_json::to_string(&with).unwrap()).unwrap(); + let round: KnockCode = + serde_json::from_str(&serde_json::to_string(&with).unwrap()).unwrap(); assert_eq!(round.monic, with.monic); } @@ -1958,7 +2015,10 @@ mod tests { let mut code = code_at(thirty_two, "doyle", 1_000); code.form = CodeForm::Legacy; - assert!(code.secret_is_well_formed(), "thirty-two hex meets the floor"); + assert!( + code.secret_is_well_formed(), + "thirty-two hex meets the floor" + ); code.form = CodeForm::Sealed; assert!( !code.secret_is_well_formed(), @@ -2502,7 +2562,10 @@ mod tests { let replaced = s.upsert(knock_at("doyle", "ling", 2_000)); assert!(replaced, "the second knock replaces rather than queues"); assert_eq!(s.knocks.len(), 1, "still exactly one pending row"); - assert_eq!(s.knocks[0].created_ms, 2_000, "the live request is the newer one"); + assert_eq!( + s.knocks[0].created_ms, 2_000, + "the live request is the newer one" + ); s.upsert(knock_at("hertz", "ling", 3_000)); s.upsert(knock_at("doyle", "flynn", 3_000)); @@ -2708,7 +2771,10 @@ mod tests { // itself too short to mint — which is the point.) #[test] fn a_code_shorter_than_the_entropy_floor_is_malformed() { - assert!(!KnockCode::is_well_formed("c0ffee"), "6 chars is not mintable"); + assert!( + !KnockCode::is_well_formed("c0ffee"), + "6 chars is not mintable" + ); assert!(!KnockCode::is_well_formed(&"a".repeat(CODE_MIN_HEX - 1))); assert!(KnockCode::is_well_formed(&"a".repeat(CODE_MIN_HEX))); assert!(KnockCode::is_well_formed(&"0123456789abcdef".repeat(2))); @@ -2774,7 +2840,10 @@ mod tests { assert!(line.contains("PARTIALLY"), "{line}"); assert!(line.contains("MSG"), "names what WAS granted: {line}"); assert!(line.contains("RC_ATTACH"), "and what was not: {line}"); - assert!(line.contains("the engine room"), "and who can finish it: {line}"); + assert!( + line.contains("the engine room"), + "and who can finish it: {line}" + ); assert!( partial.leaves_pending(), "the remainder must stay answerable — a partial does not consume the knock" @@ -2848,7 +2917,10 @@ mod tests { s.arm_mutual(pre(vec!["MSG".into(), "XFER".into()])); assert_eq!(s.pre_auths.len(), 1, "re-arming replaces, never stacks"); assert_eq!( - s.armed_mutual(PreAuthKey::Knock, "k-1").unwrap().surfaces.len(), + s.armed_mutual(PreAuthKey::Knock, "k-1") + .unwrap() + .surfaces + .len(), 2 ); @@ -3001,7 +3073,9 @@ mod tests { // due and the redemption writes no reverse rule at all. let mut one_way = KnockStore::default(); assert!( - one_way.consume_redeemed("c-9", "rita", &answered).is_empty(), + one_way + .consume_redeemed("c-9", "rita", &answered) + .is_empty(), "a one-way mint arms nothing, so its redemption owes nothing" ); } @@ -3136,7 +3210,8 @@ mod tests { ); assert!( - s.consume_redeemed("redeemed", "wanda", &answered).is_empty(), + s.consume_redeemed("redeemed", "wanda", &answered) + .is_empty(), "a replayed REDEEMED writes the reverse rule no second time" ); assert!( @@ -3317,7 +3392,10 @@ mod tests { // refuses every wire receipt: a record armed before the binding existed // was never consumable over a wire, and must not START being consumable // on a guessable key. - assert_eq!(pre.answerer_node, "", "no node was recorded, so none is trusted"); + assert_eq!( + pre.answerer_node, "", + "no node was recorded, so none is trusted" + ); let mut n_minus_one = KnockStore::default(); n_minus_one.pre_auths.push(pre.clone()); assert_eq!( @@ -3412,7 +3490,10 @@ mod tests { .expect_err("a husk must not read as an empty inbox"); assert_eq!(err.path, path); let msg = err.to_string(); - assert!(msg.contains("knocks.json"), "the diagnostic names the store: {msg}"); + assert!( + msg.contains("knocks.json"), + "the diagnostic names the store: {msg}" + ); assert!( msg.contains("cannot be listed or answered"), "and says what is broken: {msg}" @@ -3429,7 +3510,10 @@ mod tests { KnockStore::default().save_to(&path).unwrap(); let raw = std::fs::read_to_string(&path).unwrap(); - assert!(!raw.contains("knocks"), "empty collections are skipped: {raw}"); + assert!( + !raw.contains("knocks"), + "empty collections are skipped: {raw}" + ); let mut s = KnockStore::default(); s.upsert(knock_at("doyle", "ling", 1_000)); diff --git a/crates/spt-store/src/lastmsg.rs b/crates/spt-store/src/lastmsg.rs index 4b83066a..7b9478a4 100644 --- a/crates/spt-store/src/lastmsg.rs +++ b/crates/spt-store/src/lastmsg.rs @@ -159,7 +159,10 @@ mod tests { let body = "one two three four five six seven eight nine ten eleven twelve"; let (long, cut) = excerpt(body); assert_eq!(long, "one two three four five six seven eight nine ten"); - assert!(cut, "a body over the bound reports the cut rather than hiding it"); + assert!( + cut, + "a body over the bound reports the cut rather than hiding it" + ); } // [unit->REQ-NOW-SIGNAL-CATEGORIES-V1] @@ -190,8 +193,14 @@ mod tests { "nothing recorded reads as nothing, not as an error" ); - record_at(&tmp, Direction::Out, Some("doyle"), "a body worth reading", 1_700) - .unwrap(); + record_at( + &tmp, + Direction::Out, + Some("doyle"), + "a body worth reading", + 1_700, + ) + .unwrap(); let row = read_at(&tmp, Direction::Out).expect("the row just written"); assert_eq!(row.peer.as_deref(), Some("doyle")); assert_eq!(row.excerpt, "a body worth reading"); @@ -215,11 +224,8 @@ mod tests { // [unit->REQ-NOW-SIGNAL-CATEGORIES-V1] #[test] fn a_corrupt_row_reads_as_absent_rather_than_failing_the_poll() { - let tmp = std::env::temp_dir().join(format!( - "spt-lastmsg-{}-{}", - std::process::id(), - "corrupt" - )); + let tmp = + std::env::temp_dir().join(format!("spt-lastmsg-{}-{}", std::process::id(), "corrupt")); let _ = std::fs::remove_dir_all(&tmp); std::fs::create_dir_all(&tmp).unwrap(); std::fs::write(last_msg_file_at(&tmp, Direction::In), "{ not json").unwrap(); diff --git a/crates/spt-store/src/lib.rs b/crates/spt-store/src/lib.rs index ac722c84..9fc768ca 100644 --- a/crates/spt-store/src/lib.rs +++ b/crates/spt-store/src/lib.rs @@ -16,13 +16,13 @@ pub mod atomic; pub mod attachment; pub mod branchstore; pub mod briefing; +pub mod commune_intent; pub mod contacts; pub mod contextmark; -pub mod commune_intent; pub mod contextstore; pub mod daemon_inhibit; -pub mod dispatchresults; mod db; +pub mod dispatchresults; pub mod empower; pub mod engineroom; pub mod enroll; @@ -35,8 +35,8 @@ pub mod history; pub mod home; pub mod hostlabel; pub mod inbound; -pub mod iolog; pub mod info; +pub mod iolog; pub mod knock; pub mod lastmsg; pub mod liveness; @@ -49,8 +49,8 @@ pub mod peeraddrs; pub mod perch; pub mod perchgc; pub mod proc; -pub mod project; pub mod projderive; +pub mod project; pub mod projindex; pub mod projinval; pub mod psyche_custody; diff --git a/crates/spt-store/src/liveness.rs b/crates/spt-store/src/liveness.rs index 426e2f1b..9bfdf2ee 100644 --- a/crates/spt-store/src/liveness.rs +++ b/crates/spt-store/src/liveness.rs @@ -371,8 +371,7 @@ mod tests { ); let owlery = perch(); - let ep_perch = - perch::resolve_perch_path_in(owlery.path(), "ep", ParentHint::Infer); + let ep_perch = perch::resolve_perch_path_in(owlery.path(), "ep", ParentHint::Infer); std::fs::create_dir_all(&ep_perch).unwrap(); write_info( &ep_perch, diff --git a/crates/spt-store/src/matchrule.rs b/crates/spt-store/src/matchrule.rs index 5b9ce6f8..31f2a51d 100644 --- a/crates/spt-store/src/matchrule.rs +++ b/crates/spt-store/src/matchrule.rs @@ -46,7 +46,11 @@ mod tests { // fatal. #[test] fn literal_is_case_insensitive_substring_and_regex_is_opt_in() { - assert!(pattern_matches("SPT send", false, "how do i spt send a msg")); + assert!(pattern_matches( + "SPT send", + false, + "how do i spt send a msg" + )); assert!(pattern_matches("owl", false, "the OWL hoots")); assert!(!pattern_matches("owl", false, "nothing here")); @@ -76,12 +80,20 @@ mod tests { // fire on text nobody aimed it at. #[test] fn an_invalid_regex_never_matches_and_never_falls_back_to_literal() { - assert!(!pattern_matches("(unclosed", true, "(unclosed literal present")); + assert!(!pattern_matches( + "(unclosed", + true, + "(unclosed literal present" + )); assert!(!pattern_matches("[", true, "[")); assert!(!pattern_matches("a{2,1}", true, "aa")); // The control: the very same pattern, read literally, DOES match. So the // false above is the invalid-regex rule firing, not the text failing to // contain it. - assert!(pattern_matches("(unclosed", false, "(unclosed literal present")); + assert!(pattern_matches( + "(unclosed", + false, + "(unclosed literal present" + )); } } diff --git a/crates/spt-store/src/monic.rs b/crates/spt-store/src/monic.rs index 2e85c836..4d5f51c9 100644 --- a/crates/spt-store/src/monic.rs +++ b/crates/spt-store/src/monic.rs @@ -438,7 +438,8 @@ fn parse_monic(bytes: &[u8]) -> Option { fn monics_dir(cs: &ContextStore, owner: &str) -> io::Result { validated(owner)?; let wt = cs.root().join("agents").join(owner); - cs.branch_store().ensure_worktree(&agent_branch(owner), &wt)?; + cs.branch_store() + .ensure_worktree(&agent_branch(owner), &wt)?; Ok(wt.join(MONICS_DIR)) } @@ -560,7 +561,9 @@ pub fn write_monic( (WriteMode::Update, false) => return Ok(Err(WriteRefusal::Missing)), _ => {} } - Ok(Ok(set_monic(cs, owner, id, triggers, text, set_ms, origin)?)) + Ok(Ok(set_monic( + cs, owner, id, triggers, text, set_ms, origin, + )?)) } /// One row of a monic listing: the id a record is filed under, and the record @@ -1021,7 +1024,10 @@ pub fn clone_monics( offered .iter() .filter(|rel| held.contains(rel)) - .filter_map(|rel| rel.strip_prefix(&format!("{MONICS_DIR}/")).map(str::to_string)) + .filter_map(|rel| { + rel.strip_prefix(&format!("{MONICS_DIR}/")) + .map(str::to_string) + }) .collect() }; @@ -1232,7 +1238,14 @@ mod tests { ); // 3. Several records, one peer. Both ride the delivery. - classify(&cs, "doyle", "second-note", "mallory", "also: slow to reply", 3); + classify( + &cs, + "doyle", + "second-note", + "mallory", + "also: slow to reply", + 3, + ); let json = matched_for_delivery(&root, "doyle", "mallory", "any body").unwrap(); let decoded: Vec = serde_json::from_str(&json).unwrap(); let ids: Vec<&str> = decoded.iter().map(|m| m.id.as_str()).collect(); @@ -1319,7 +1332,14 @@ mod tests { // A common ancestor, so the divergence below is a genuine concurrent // pair rather than an adopt. - classify(&a, "doyle", "shared-note", "shared", "known before the split", 1); + classify( + &a, + "doyle", + "shared-note", + "shared", + "known before the split", + 1, + ); let adopt = ship(&a, &b, &branch, ship_dir.path()); assert!(adopt.adopted || adopt.conflicted.is_empty()); @@ -1443,7 +1463,10 @@ mod tests { }; // update before anything exists: refused as Missing, and writes nothing. - assert_eq!(mk(WriteMode::Update, "invented"), Err(WriteRefusal::Missing)); + assert_eq!( + mk(WriteMode::Update, "invented"), + Err(WriteRefusal::Missing) + ); assert!(!record_present(&cs, "doyle", "note-1").unwrap()); assert!(mk(WriteMode::Add, "first").is_ok()); @@ -1677,7 +1700,11 @@ mod tests { } // A husk classifies nobody, and a traversal peer id is refused. - std::fs::write(monic_file(&cs, "doyle", "about-mallory").unwrap(), b"{ torn").unwrap(); + std::fs::write( + monic_file(&cs, "doyle", "about-mallory").unwrap(), + b"{ torn", + ) + .unwrap(); assert!(!has_monic_at(&root, "doyle", "mallory")); assert!(!has_monic_at(&root, "doyle", "../../escape")); assert!(matched_for_delivery(&root, "doyle", "../../escape", "x").is_none()); @@ -1863,7 +1890,11 @@ mod tests { // A husk in the source: a real file, unreadable. It must travel as a // file rather than being dropped or invented on the far side. classify(&cs, "doyle", "note-torn", "cass", "torn", 3); - std::fs::write(monic_file(&cs, "doyle", "note-torn").unwrap(), b"{ not json").unwrap(); + std::fs::write( + monic_file(&cs, "doyle", "note-torn").unwrap(), + b"{ not json", + ) + .unwrap(); // Committed as a husk: a clone copies the mind at its TIP. cs.commit_live("doyle", "a torn record").unwrap(); @@ -1889,7 +1920,10 @@ mod tests { assert_eq!(copied, vec!["note-td", "note-torn"]); assert_eq!( - get_monic(&cs, "momo", "note-mallory").unwrap().unwrap().text, + get_monic(&cs, "momo", "note-mallory") + .unwrap() + .unwrap() + .text, "my operator", "the destination's own record is NOT clobbered" ); @@ -1926,7 +1960,10 @@ mod tests { assert_eq!(report.len(), 1); assert!(!report[0].kept_existing); assert_eq!( - get_monic(&cs, "momo", "note-mallory").unwrap().unwrap().text, + get_monic(&cs, "momo", "note-mallory") + .unwrap() + .unwrap() + .text, "unverified" ); diff --git a/crates/spt-store/src/notif.rs b/crates/spt-store/src/notif.rs index 303f2e40..2d9f5686 100644 --- a/crates/spt-store/src/notif.rs +++ b/crates/spt-store/src/notif.rs @@ -277,7 +277,16 @@ impl NotifStore { expires_ms: Option, ) -> rusqlite::Result { self.produce_full( - node_hex, epochs, subnet, kind, from_id, body, scope, coalesce_key, expires_ms, None, + node_hex, + epochs, + subnet, + kind, + from_id, + body, + scope, + coalesce_key, + expires_ms, + None, ) } @@ -764,7 +773,11 @@ mod tests { no longer rides this field" ); assert_eq!( - s.get(&addressed.notif_id).unwrap().unwrap().to_id.as_deref(), + s.get(&addressed.notif_id) + .unwrap() + .unwrap() + .to_id + .as_deref(), Some("doyle"), "and the addressee survives the SQLite round trip" ); @@ -982,8 +995,15 @@ mod tests { for bad in ["update-staged", ":no-owner", "no-key:", ""] { let err = s .produce_scoped( - "cafe", &mut e, "home", "update", "spt-update", "x", - NotifScope::Node, Some(bad), None, + "cafe", + &mut e, + "home", + "update", + "spt-update", + "x", + NotifScope::Node, + Some(bad), + None, ) .unwrap_err(); assert!( @@ -991,12 +1011,22 @@ mod tests { "bare key {bad:?} rejected with the pinned copy: {err}" ); } - assert!(s.list("home").unwrap().is_empty(), "no row written on reject"); + assert!( + s.list("home").unwrap().is_empty(), + "no row written on reject" + ); let ok = s .produce_scoped( - "cafe", &mut e, "home", "update", "spt-update", "x", - NotifScope::Node, Some("spt-core:update-staged"), None, + "cafe", + &mut e, + "home", + "update", + "spt-update", + "x", + NotifScope::Node, + Some("spt-core:update-staged"), + None, ) .unwrap(); assert_eq!(ok.coalesce_key.as_deref(), Some("spt-core:update-staged")); @@ -1016,35 +1046,91 @@ mod tests { let key = Some("spt-core:update-staged"); let first = s - .produce_scoped("cafe", &mut e, "home", "consent", "spt-update", "v1", - NotifScope::Node, key, None) + .produce_scoped( + "cafe", + &mut e, + "home", + "consent", + "spt-update", + "v1", + NotifScope::Node, + key, + None, + ) .unwrap(); // Same tuple: supersedes the first (latest-wins). let second = s - .produce_scoped("cafe", &mut e, "home", "consent", "spt-update", "v2", - NotifScope::Node, key, None) + .produce_scoped( + "cafe", + &mut e, + "home", + "consent", + "spt-update", + "v2", + NotifScope::Node, + key, + None, + ) .unwrap(); - assert!(s.get(&first.notif_id).unwrap().unwrap().dismissed, "prior superseded"); - assert!(!s.get(&second.notif_id).unwrap().unwrap().dismissed, "latest lives"); + assert!( + s.get(&first.notif_id).unwrap().unwrap().dismissed, + "prior superseded" + ); + assert!( + !s.get(&second.notif_id).unwrap().unwrap().dismissed, + "latest lives" + ); // Same key, different KIND: does not touch the live consent row. - s.produce_scoped("cafe", &mut e, "home", "rollback", "spt-update", "r", - NotifScope::Node, key, None) - .unwrap(); - assert!(!s.get(&second.notif_id).unwrap().unwrap().dismissed, "different kind spared"); + s.produce_scoped( + "cafe", + &mut e, + "home", + "rollback", + "spt-update", + "r", + NotifScope::Node, + key, + None, + ) + .unwrap(); + assert!( + !s.get(&second.notif_id).unwrap().unwrap().dismissed, + "different kind spared" + ); // Same key + kind, different SCOPE: does not supersede the node row. - s.produce_scoped("cafe", &mut e, "home", "consent", "spt-update", "sub", - NotifScope::Subnet, key, None) - .unwrap(); - assert!(!s.get(&second.notif_id).unwrap().unwrap().dismissed, "different scope spared"); + s.produce_scoped( + "cafe", + &mut e, + "home", + "consent", + "spt-update", + "sub", + NotifScope::Subnet, + key, + None, + ) + .unwrap(); + assert!( + !s.get(&second.notif_id).unwrap().unwrap().dismissed, + "different scope spared" + ); // A keyless produce supersedes nothing. let live: Vec<_> = s - .undismissed("home").unwrap().iter().map(|r| r.notif_id.clone()).collect(); - s.produce("cafe", &mut e, "home", "consent", "spt-update", "keyless").unwrap(); + .undismissed("home") + .unwrap() + .iter() + .map(|r| r.notif_id.clone()) + .collect(); + s.produce("cafe", &mut e, "home", "consent", "spt-update", "keyless") + .unwrap(); for id in &live { - assert!(!s.get(id).unwrap().unwrap().dismissed, "keyless supersedes nothing"); + assert!( + !s.get(id).unwrap().unwrap().dismissed, + "keyless supersedes nothing" + ); } } @@ -1059,24 +1145,59 @@ mod tests { let mut e = epochs(dir.path()); let expired = s - .produce_scoped("cafe", &mut e, "home", "agent", "ling", "gone", - NotifScope::Subnet, None, Some(1_000)) + .produce_scoped( + "cafe", + &mut e, + "home", + "agent", + "ling", + "gone", + NotifScope::Subnet, + None, + Some(1_000), + ) .unwrap(); // Seen everywhere — expiry must not care. s.mark_seen(&expired.notif_id, "doyle").unwrap(); let future = s - .produce_scoped("cafe", &mut e, "home", "agent", "ling", "fresh", - NotifScope::Subnet, None, Some(9_000)) + .produce_scoped( + "cafe", + &mut e, + "home", + "agent", + "ling", + "fresh", + NotifScope::Subnet, + None, + Some(9_000), + ) .unwrap(); let no_ttl = s .produce("cafe", &mut e, "home", "agent", "ling", "forever") .unwrap(); - assert_eq!(s.expire_due("home", 5_000).unwrap(), 1, "only the expired one"); - assert!(s.get(&expired.notif_id).unwrap().unwrap().dismissed, "expired despite seen"); - assert!(!s.get(&future.notif_id).unwrap().unwrap().dismissed, "not yet due"); - assert!(!s.get(&no_ttl.notif_id).unwrap().unwrap().dismissed, "no ttl, never expires"); - assert_eq!(s.expire_due("home", 5_000).unwrap(), 0, "idempotent — nothing new"); + assert_eq!( + s.expire_due("home", 5_000).unwrap(), + 1, + "only the expired one" + ); + assert!( + s.get(&expired.notif_id).unwrap().unwrap().dismissed, + "expired despite seen" + ); + assert!( + !s.get(&future.notif_id).unwrap().unwrap().dismissed, + "not yet due" + ); + assert!( + !s.get(&no_ttl.notif_id).unwrap().unwrap().dismissed, + "no ttl, never expires" + ); + assert_eq!( + s.expire_due("home", 5_000).unwrap(), + 0, + "idempotent — nothing new" + ); } // [unit->REQ-NOTIF-MIGRATE] the one-shot migration dismisses ONLY the @@ -1089,19 +1210,42 @@ mod tests { let s = store(dir.path()); let mut e = epochs(dir.path()); - let consent = s.produce("cafe", &mut e, "home", "consent", "spt-update", "u").unwrap(); - let rollback = s.produce("cafe", &mut e, "home", "rollback", "spt-update", "r").unwrap(); - let agent = s.produce("cafe", &mut e, "home", "agent", "ling", "build").unwrap(); - let psyche = s.produce("cafe", &mut e, "home", "psyche", "ling", "sync").unwrap(); + let consent = s + .produce("cafe", &mut e, "home", "consent", "spt-update", "u") + .unwrap(); + let rollback = s + .produce("cafe", &mut e, "home", "rollback", "spt-update", "r") + .unwrap(); + let agent = s + .produce("cafe", &mut e, "home", "agent", "ling", "build") + .unwrap(); + let psyche = s + .produce("cafe", &mut e, "home", "psyche", "ling", "sync") + .unwrap(); // An update-kind row from some other issuer is not the known-stale class. - let other = s.produce("cafe", &mut e, "home", "consent", "someone-else", "x").unwrap(); + let other = s + .produce("cafe", &mut e, "home", "consent", "someone-else", "x") + .unwrap(); - assert_eq!(s.dismiss_stale_update_rows().unwrap(), 2, "consent + rollback"); + assert_eq!( + s.dismiss_stale_update_rows().unwrap(), + 2, + "consent + rollback" + ); assert!(s.get(&consent.notif_id).unwrap().unwrap().dismissed); assert!(s.get(&rollback.notif_id).unwrap().unwrap().dismissed); - assert!(!s.get(&agent.notif_id).unwrap().unwrap().dismissed, "agent untouched"); - assert!(!s.get(&psyche.notif_id).unwrap().unwrap().dismissed, "psyche untouched"); - assert!(!s.get(&other.notif_id).unwrap().unwrap().dismissed, "other issuer untouched"); + assert!( + !s.get(&agent.notif_id).unwrap().unwrap().dismissed, + "agent untouched" + ); + assert!( + !s.get(&psyche.notif_id).unwrap().unwrap().dismissed, + "psyche untouched" + ); + assert!( + !s.get(&other.notif_id).unwrap().unwrap().dismissed, + "other issuer untouched" + ); assert_eq!(s.dismiss_stale_update_rows().unwrap(), 0, "idempotent"); } @@ -1116,25 +1260,66 @@ mod tests { let key = Some("spt-core:update-staged"); let staged = s - .produce_scoped("cafe", &mut e, "home", "consent", "spt-update", "u", - NotifScope::Node, key, None) + .produce_scoped( + "cafe", + &mut e, + "home", + "consent", + "spt-update", + "u", + NotifScope::Node, + key, + None, + ) .unwrap(); let other_key = s - .produce_scoped("cafe", &mut e, "home", "rollback", "spt-update", "r", - NotifScope::Node, Some("spt-core:rollback"), None) + .produce_scoped( + "cafe", + &mut e, + "home", + "rollback", + "spt-update", + "r", + NotifScope::Node, + Some("spt-core:rollback"), + None, + ) .unwrap(); // Same key, different subnet: untouched. let other_subnet = s - .produce_scoped("cafe", &mut e, "work", "consent", "spt-update", "w", - NotifScope::Node, key, None) + .produce_scoped( + "cafe", + &mut e, + "work", + "consent", + "spt-update", + "w", + NotifScope::Node, + key, + None, + ) .unwrap(); - assert_eq!(s.dismiss_by_coalesce_key("home", "spt-core:update-staged").unwrap(), 1); - assert!(s.get(&staged.notif_id).unwrap().unwrap().dismissed, "keyed row latched"); - assert!(!s.get(&other_key.notif_id).unwrap().unwrap().dismissed, "different key spared"); - assert!(!s.get(&other_subnet.notif_id).unwrap().unwrap().dismissed, "different subnet spared"); assert_eq!( - s.dismiss_by_coalesce_key("home", "spt-core:update-staged").unwrap(), + s.dismiss_by_coalesce_key("home", "spt-core:update-staged") + .unwrap(), + 1 + ); + assert!( + s.get(&staged.notif_id).unwrap().unwrap().dismissed, + "keyed row latched" + ); + assert!( + !s.get(&other_key.notif_id).unwrap().unwrap().dismissed, + "different key spared" + ); + assert!( + !s.get(&other_subnet.notif_id).unwrap().unwrap().dismissed, + "different subnet spared" + ); + assert_eq!( + s.dismiss_by_coalesce_key("home", "spt-core:update-staged") + .unwrap(), 0, "idempotent" ); diff --git a/crates/spt-store/src/obstap.rs b/crates/spt-store/src/obstap.rs index 15e1397a..11856e24 100644 --- a/crates/spt-store/src/obstap.rs +++ b/crates/spt-store/src/obstap.rs @@ -62,7 +62,11 @@ pub fn breadcrumb(basename: &str, line: &str) { if at_cap(&path) { return; } - if let Ok(mut f) = std::fs::OpenOptions::new().create(true).append(true).open(&path) { + if let Ok(mut f) = std::fs::OpenOptions::new() + .create(true) + .append(true) + .open(&path) + { let _ = writeln!(f, "t={} {line}", now_ms()); } } @@ -95,7 +99,11 @@ pub fn tap(session_id: u64, which: &str, bytes: &[u8]) { use std::fmt::Write as _; let _ = write!(hex, "{b:02x}"); } - if let Ok(mut f) = std::fs::OpenOptions::new().create(true).append(true).open(&path) { + if let Ok(mut f) = std::fs::OpenOptions::new() + .create(true) + .append(true) + .open(&path) + { let _ = writeln!(f, "t={} n={} {hex}", now_ms(), bytes.len()); } } diff --git a/crates/spt-store/src/peeraddrs.rs b/crates/spt-store/src/peeraddrs.rs index e40b67a4..495cb3c7 100644 --- a/crates/spt-store/src/peeraddrs.rs +++ b/crates/spt-store/src/peeraddrs.rs @@ -287,16 +287,26 @@ mod tests { for _ in 0..5 { PeerAddrStore::demote_seed(&path, "ab12").unwrap(); let s = PeerAddrStore::load_from(&path); - assert_eq!(s.get("ab12"), Some(&addr), "the address survives the failure"); + assert_eq!( + s.get("ab12"), + Some(&addr), + "the address survives the failure" + ); assert!(s.is_suspect("ab12"), "and is marked suspect"); - assert!(s.valid_route("ab12").is_none(), "a suspect row is not a route"); + assert!( + s.valid_route("ab12").is_none(), + "a suspect row is not a route" + ); } // A validated fresher address supersedes: mark cleared, route live. let fresher = serde_json::json!({"id": "ab12", "addrs": ["10.0.0.9:4711"]}); let mut s = PeerAddrStore::load_from(&path); assert!(s.put("ab12", fresher.clone()), "supersede is a change"); - assert!(!s.is_suspect("ab12"), "suspect cleared by the validated put"); + assert!( + !s.is_suspect("ab12"), + "suspect cleared by the validated put" + ); assert_eq!(s.valid_route("ab12"), Some(&fresher), "route restored"); // Re-putting the SAME addr on a suspect row also un-suspects (a @@ -304,7 +314,10 @@ mod tests { let mut s2 = PeerAddrStore::default(); assert!(s2.put("ab12", addr.clone())); s2.mark_suspect("ab12"); - assert!(s2.put("ab12", addr), "same-addr put on a suspect row = a change (the mark)"); + assert!( + s2.put("ab12", addr), + "same-addr put on a suspect row = a change (the mark)" + ); assert!(!s2.is_suspect("ab12")); } @@ -320,8 +333,14 @@ mod tests { "5ff50e75".to_string(), serde_json::json!({"id": "ecb39aaa", "addrs": ["10.0.0.2:4711"]}), ); - assert!(store.valid_route("5ff50e75").is_none(), "poison row is not a route"); - assert!(store.get("5ff50e75").is_some(), "but stays readable for repair"); + assert!( + store.valid_route("5ff50e75").is_none(), + "poison row is not a route" + ); + assert!( + store.get("5ff50e75").is_some(), + "but stays readable for repair" + ); } // [unit->REQ-PEER-ROUTE-CHAIN] suspect state round-trips through disk diff --git a/crates/spt-store/src/perch.rs b/crates/spt-store/src/perch.rs index 74681595..ad67450d 100644 --- a/crates/spt-store/src/perch.rs +++ b/crates/spt-store/src/perch.rs @@ -943,7 +943,10 @@ pub fn list_nested_perch_dirs_in(owlery: &Path, parent: &str) -> Vec Vec Vec { list_nested_perch_dirs_in(owlery, parent) .iter() - .filter_map(|d| d.dir.file_name().and_then(|n| n.to_str()).map(str::to_string)) + .filter_map(|d| { + d.dir + .file_name() + .and_then(|n| n.to_str()) + .map(str::to_string) + }) .collect() } @@ -1503,8 +1511,20 @@ mod tests { // Bulk injectivity over a set containing every adversarial neighbour. let options = [ - "cc", "cc:dev", "cc_dev", "cc:dev:extra", "cc%3Adev", "cc.dev", "cc dev", "cc/dev", - r"cc\dev", "CC", "cc:", ":cc", "", "cc:DEV", + "cc", + "cc:dev", + "cc_dev", + "cc:dev:extra", + "cc%3Adev", + "cc.dev", + "cc dev", + "cc/dev", + r"cc\dev", + "CC", + "cc:", + ":cc", + "", + "cc:DEV", ]; let mut seen = std::collections::BTreeMap::new(); for o in options { diff --git a/crates/spt-store/src/perchgc.rs b/crates/spt-store/src/perchgc.rs index b36df7a6..0ba76c25 100644 --- a/crates/spt-store/src/perchgc.rs +++ b/crates/spt-store/src/perchgc.rs @@ -186,7 +186,10 @@ impl PerchClass { /// reported with a manual remedy precisely because nothing will ever heal /// them automatically. pub fn is_refused_residue(self) -> bool { - matches!(self, PerchClass::ResidueWithSpool | PerchClass::ResidueEmpty) + matches!( + self, + PerchClass::ResidueWithSpool | PerchClass::ResidueEmpty + ) } /// The manual remedy line for a refused residue class — the operator's @@ -345,7 +348,9 @@ fn classify_slot(dir: &Path, depth: usize, out: &mut Vec) { e.depth != depth + 1 || e.class == PerchClass::Reapable }); let class = match class { - PerchClass::Reapable if !children_all_reapable => PerchClass::Occupied(Occupancy::ChildHeld), + PerchClass::Reapable if !children_all_reapable => { + PerchClass::Occupied(Occupancy::ChildHeld) + } other => other, }; // THE SHIELD (doyle, ruled 2026-08-04). A directory the sweep refuses keeps @@ -615,7 +620,9 @@ mod tests { .entries .iter() .find(|e| e.id == id) - .unwrap_or_else(|| panic!("no sweep entry for '{id}' — the sweep never saw its subject")) + .unwrap_or_else(|| { + panic!("no sweep entry for '{id}' — the sweep never saw its subject") + }) } // ── the negative control: the sweep DECLINES a live endpoint ───────────── @@ -644,7 +651,10 @@ mod tests { PerchClass::Occupied(Occupancy::Record), "an OFFLINE endpoint is an endpoint: absence from the registry is its normal state" ); - assert!(live.join("info.json").exists(), "live record survives --reap"); + assert!( + live.join("info.json").exists(), + "live record survives --reap" + ); assert!( resting.join("info.json").exists(), "offline record survives --reap" @@ -714,7 +724,10 @@ mod tests { "an empty dir is also what a bringup owns mid-create" ); assert!(!reapable.exists(), "the ruled population is reaped"); - assert!(spooled.join("spool.db").exists(), "the spool survives --reap"); + assert!( + spooled.join("spool.db").exists(), + "the spool survives --reap" + ); assert!(empty.exists(), "the empty dir survives --reap"); } @@ -852,7 +865,11 @@ mod tests { "the shield reaches the whole subtree, not one level" ); assert!(grandchild.exists() && child.exists() && parent.exists()); - assert_eq!(report.reaped().count(), 0, "nothing under a refusal is touched"); + assert_eq!( + report.reaped().count(), + 0, + "nothing under a refusal is touched" + ); assert!( PerchClass::ShieldedByRefusedParent.remedy().is_some(), "a shielded row names what to resolve first" @@ -925,7 +942,10 @@ mod tests { let empty_root = owlery(); let ok = sweep(empty_root.path(), true); - assert!(ok.root_readable, "an EMPTY owlery is readable — not the same"); + assert!( + ok.root_readable, + "an EMPTY owlery is readable — not the same" + ); assert!(ok.entries.is_empty()); } @@ -959,7 +979,11 @@ mod tests { shape(&reaping), "classification must not depend on whether deletion was authorized" ); - assert_eq!(reported.reaped().count(), 0, "a bare report deletes nothing"); + assert_eq!( + reported.reaped().count(), + 0, + "a bare report deletes nothing" + ); assert_eq!(reaping.reaped().count(), 1); } diff --git a/crates/spt-store/src/proc.rs b/crates/spt-store/src/proc.rs index bc6d765b..4bb8b064 100644 --- a/crates/spt-store/src/proc.rs +++ b/crates/spt-store/src/proc.rs @@ -17,8 +17,6 @@ pub use spt_procident::{ process_started_at, process_table, PinnedProc, ProcIdentity, }; - - /// Best-effort reap of an exited child: clears the zombie a kill (or a plain /// exit) leaves when the **spawner itself keeps running** — in-process daemon /// hosting and tests; a short-lived CLI spawner exits and init/the OS reaps @@ -155,7 +153,9 @@ pub fn process_cmdline(pid: u32) -> Option { &mut needed, ) }; - if probe == STATUS_INFO_LENGTH_MISMATCH && needed >= core::mem::size_of::() as u32 { + if probe == STATUS_INFO_LENGTH_MISMATCH + && needed >= core::mem::size_of::() as u32 + { let mut buf = vec![0u8; needed as usize]; let status = unsafe { NtQueryInformationProcess( @@ -247,7 +247,6 @@ pub fn parent_pid() -> Option { } } - /// The current process's ANCESTRY pids (parent, grandparent, …), bounded and /// cycle-guarded — the set matched against roster perch pids for self-identification /// when the env self-id legs are absent (REQ-MSG-SELF-DETECT-ANCESTRY). The FIRST @@ -271,7 +270,6 @@ pub fn process_ancestry() -> Vec { out } - /// **The canonical answer to "is a process I OWN gone?"** — the one question /// KNOWN-HAZARDS 7.50 names as the dangerous shape, given one implementation so /// that every consumer asking it gets the same answer. @@ -332,7 +330,6 @@ pub fn provably_gone(pid: u32) -> bool { } } - /// When this machine last booted, as wall-clock epoch-ms — `None` when the /// platform will not say (never a guessed value). /// @@ -376,9 +373,6 @@ pub fn boot_instant_ms() -> Option { } } - - - /// The DESCENDANT pids of `root` (children, grandchildren, …) — NOT including /// `root` — computed from a single [`process_table`] snapshot by a BFS over the /// parent→children map. Scope-strict: ONLY processes whose parent-chain reaches @@ -590,7 +584,10 @@ mod tests { .and_then(|p| p.file_name().map(|s| s.to_string_lossy().into_owned())); let got = exe_basename(std::process::id()); assert!(got.is_some(), "the current process's exe basename resolves"); - assert!(!got.as_deref().unwrap_or("").is_empty(), "basename non-empty"); + assert!( + !got.as_deref().unwrap_or("").is_empty(), + "basename non-empty" + ); assert_eq!(got, want, "matches current_exe's basename"); } @@ -599,7 +596,10 @@ mod tests { #[test] fn exe_basename_dead_pid_is_none() { const DEAD_PID: u32 = 2_000_000_000; - assert!(exe_basename(DEAD_PID).is_none(), "no basename for a dead pid"); + assert!( + exe_basename(DEAD_PID).is_none(), + "no basename for a dead pid" + ); assert!(exe_basename(0).is_none(), "pid 0 is never probe-able"); } @@ -642,7 +642,10 @@ mod tests { } let _ = child.kill(); let _ = child.wait(); - assert!(found, "process_cmdline must read a live child's argv marker"); + assert!( + found, + "process_cmdline must read a live child's argv marker" + ); assert!( process_cmdline(2_000_000_000).is_none(), "a dead pid yields no cmdline (fail-safe → caller declines to reap)" @@ -707,10 +710,16 @@ mod tests { .spawn() .expect("spawn a real child to make a corpse of"); let pid = child.id(); - assert_eq!(process_exists(pid), Some(true), "precondition: it is running"); + assert_eq!( + process_exists(pid), + Some(true), + "precondition: it is running" + ); child.kill().expect("kill the child"); - child.wait().expect("reap it — it is genuinely terminated now"); + child + .wait() + .expect("reap it — it is genuinely terminated now"); // `child` is deliberately NOT dropped: the handle stays open below. assert!( @@ -888,9 +897,15 @@ mod tests { } let _ = child.kill(); let _ = child.wait(); - assert!(found, "a spawned child must be found in the descendant subtree"); + assert!( + found, + "a spawned child must be found in the descendant subtree" + ); // Root/0 guards: never claim descendants for the never-probe-able pid. - assert!(process_descendants(0).is_empty(), "pid 0 has no descendants"); + assert!( + process_descendants(0).is_empty(), + "pid 0 has no descendants" + ); } /// A 2-LEVEL tree: a resident parent (`cmd`/`sh`) that itself spawns a diff --git a/crates/spt-store/src/projderive.rs b/crates/spt-store/src/projderive.rs index 820843d2..b4facfd7 100644 --- a/crates/spt-store/src/projderive.rs +++ b/crates/spt-store/src/projderive.rs @@ -125,7 +125,12 @@ pub fn project_refs_from( continue; } if seen_id.insert(pid.clone()) { - refs.push(DerivedRef { id: pid, dir: cwd.to_string(), display, source }); + refs.push(DerivedRef { + id: pid, + dir: cwd.to_string(), + display, + source, + }); } } // UNION the committed-context branches (project ids only; no session dir → the @@ -191,7 +196,10 @@ mod tests { let origin = refs.iter().find(|r| r.id == "origin").expect("origin ref"); assert_eq!(origin.source, SourceLeg::OriginCwd); // Branch-only membership appends last, display = id verbatim. - let store = refs.iter().find(|r| r.id == "store-proj").expect("store ref"); + let store = refs + .iter() + .find(|r| r.id == "store-proj") + .expect("store ref"); assert_eq!(store.source, SourceLeg::ContextRecency); assert_eq!(store.display, "store-proj"); assert_eq!(store.dir, ""); @@ -201,8 +209,13 @@ mod tests { assert_eq!(refs[0].source, SourceLeg::OriginCwd); // Nothing but branches → context recency decides the head. - let refs = - project_refs_from(&[], None, vec!["only-store".to_string()], owlery, stub_derive); + let refs = project_refs_from( + &[], + None, + vec!["only-store".to_string()], + owlery, + stub_derive, + ); assert_eq!(refs[0].source, SourceLeg::ContextRecency); } @@ -221,7 +234,7 @@ mod tests { entry(Some("/p/proj-a")), entry(Some("/home/owlery/x/nested/x-psyche")), // owlery-internal: excluded entry(Some("/p/proj-a")), // repeat cwd: one derivation - entry(Some("/other/PROJ-A")), // same id, different dir: newest dir kept + entry(Some("/other/PROJ-A")), // same id, different dir: newest dir kept ]; let refs = project_refs_from(&entries, None, vec![], owlery, counting); assert_eq!(refs.len(), 1, "one project id → one ref: {refs:?}"); @@ -242,12 +255,18 @@ mod tests { // owlery-exclusion prefix test rides the same normalization. #[test] fn normalization_and_path_under() { - assert_eq!(normalize_path(Path::new("C:\\Users\\X\\Proj\\")), "c:/users/x/proj"); + assert_eq!( + normalize_path(Path::new("C:\\Users\\X\\Proj\\")), + "c:/users/x/proj" + ); assert!(path_under( Path::new("C:\\home\\OWLERY\\a\\nested"), Path::new("c:/home/owlery") )); - assert!(!path_under(Path::new("/home/owl"), Path::new("/home/owlery"))); + assert!(!path_under( + Path::new("/home/owl"), + Path::new("/home/owlery") + )); assert!(!path_under(Path::new("/anything"), Path::new(""))); } } diff --git a/crates/spt-store/src/project.rs b/crates/spt-store/src/project.rs index 0b70e10e..1912124d 100644 --- a/crates/spt-store/src/project.rs +++ b/crates/spt-store/src/project.rs @@ -134,7 +134,11 @@ pub fn project_id_and_display_for_dir(dir: &Path) -> (String, String) { .file_name() .map(|n| n.to_string_lossy().to_string()) .unwrap_or_default(); - let id = if name.is_empty() { String::new() } else { slug(&name) }; + let id = if name.is_empty() { + String::new() + } else { + slug(&name) + }; if id.is_empty() { ("unnamed-project".to_string(), "unnamed-project".to_string()) } else { @@ -194,8 +198,14 @@ mod tests { #[test] // [unit->REQ-PICKER-PROJECT-DISPLAY-NAME] display = URL tail / folder name, case preserved, never parsed out of the lossy slug. fn display_derivation() { // display_from_url: last path segment, `.git` + trailing slash stripped. - assert_eq!(display_from_url("https://github.com/SaberMage/spt-core.git"), "spt-core"); - assert_eq!(display_from_url("git@github.com:SaberMage/spt-core.git"), "spt-core"); + assert_eq!( + display_from_url("https://github.com/SaberMage/spt-core.git"), + "spt-core" + ); + assert_eq!( + display_from_url("git@github.com:SaberMage/spt-core.git"), + "spt-core" + ); assert_eq!(display_from_url("https://example.com/Team/Repo/"), "Repo"); // One-pass derivation: id keys on the slug, display stays recognizable. @@ -208,12 +218,22 @@ mod tests { assert_eq!((id.as_str(), disp.as_str()), ("proj-x", "proj-x")); // With a remote → id slugged, display = URL tail (case preserved). run_git_ok( - &["-C", &root.to_string_lossy(), "remote", "add", "origin", "git@example.com:Team/CoolRepo.git"], + &[ + "-C", + &root.to_string_lossy(), + "remote", + "add", + "origin", + "git@example.com:Team/CoolRepo.git", + ], None, None, ) .unwrap(); let (id, disp) = project_id_and_display_for_dir(&root.join("nested")); - assert_eq!((id.as_str(), disp.as_str()), ("example-com-team-coolrepo", "CoolRepo")); + assert_eq!( + (id.as_str(), disp.as_str()), + ("example-com-team-coolrepo", "CoolRepo") + ); } } diff --git a/crates/spt-store/src/projinval.rs b/crates/spt-store/src/projinval.rs index c0d52439..e80818ca 100644 --- a/crates/spt-store/src/projinval.rs +++ b/crates/spt-store/src/projinval.rs @@ -174,10 +174,20 @@ mod tests { nudge_at(&dir, &InvalScope::Global).unwrap(); nudge_at( &dir, - &InvalScope::Endpoint { id: "todlando".into(), cwd: Some("C:/p/spt-core".into()) }, + &InvalScope::Endpoint { + id: "todlando".into(), + cwd: Some("C:/p/spt-core".into()), + }, + ) + .unwrap(); + nudge_at( + &dir, + &InvalScope::Endpoint { + id: "perri".into(), + cwd: None, + }, ) .unwrap(); - nudge_at(&dir, &InvalScope::Endpoint { id: "perri".into(), cwd: None }).unwrap(); assert!(pending_at(&dir)); let drained = drain_at(&dir); @@ -193,10 +203,19 @@ mod tests { #[test] fn burst_coalesces_into_one_refresh() { let batch = vec![ - InvalScope::Endpoint { id: "a".into(), cwd: Some("/p/x".into()) }, + InvalScope::Endpoint { + id: "a".into(), + cwd: Some("/p/x".into()), + }, InvalScope::Global, - InvalScope::Endpoint { id: "a".into(), cwd: Some("/p/x".into()) }, - InvalScope::Endpoint { id: "b".into(), cwd: None }, + InvalScope::Endpoint { + id: "a".into(), + cwd: Some("/p/x".into()), + }, + InvalScope::Endpoint { + id: "b".into(), + cwd: None, + }, InvalScope::Global, ]; let one = coalesce(batch); @@ -223,6 +242,9 @@ mod tests { let drained = drain_at(&dir); assert_eq!(drained, vec![InvalScope::Global]); - assert!(!pending_at(&dir), "garbage is consumed too, not left to wedge"); + assert!( + !pending_at(&dir), + "garbage is consumed too, not left to wedge" + ); } } diff --git a/crates/spt-store/src/recent_home.rs b/crates/spt-store/src/recent_home.rs index d583cb2d..9b0445de 100644 --- a/crates/spt-store/src/recent_home.rs +++ b/crates/spt-store/src/recent_home.rs @@ -118,7 +118,10 @@ mod tests { #[test] fn node_global_moves_to_front() { let d = tempfile::tempdir().unwrap(); - assert!(mru_preference_in(d.path(), None).is_empty(), "unset → empty"); + assert!( + mru_preference_in(d.path(), None).is_empty(), + "unset → empty" + ); record_home_in(d.path(), None, "bignet"); record_home_in(d.path(), None, "homenet"); assert_eq!( @@ -175,12 +178,16 @@ mod tests { let d = tempfile::tempdir().unwrap(); record_home_in(d.path(), Some("proj-x"), "workv"); assert_eq!( - mru_preference_in(d.path(), Some("proj-x")).first().map(String::as_str), + mru_preference_in(d.path(), Some("proj-x")) + .first() + .map(String::as_str), Some("workv"), "project list recorded" ); assert_eq!( - mru_preference_in(d.path(), Some("other")).first().map(String::as_str), + mru_preference_in(d.path(), Some("other")) + .first() + .map(String::as_str), Some("workv"), "node-global fallback recorded for an unrelated project" ); @@ -192,7 +199,10 @@ mod tests { fn blank_name_is_noop() { let d = tempfile::tempdir().unwrap(); record_home_in(d.path(), None, " "); - assert!(mru_preference_in(d.path(), None).is_empty(), "whitespace-only → no record"); + assert!( + mru_preference_in(d.path(), None).is_empty(), + "whitespace-only → no record" + ); } // [unit->REQ-RUN-MULTISUBNET-HOME] a pre-W3 single-value `recent_home` file diff --git a/crates/spt-store/src/resume_custody.rs b/crates/spt-store/src/resume_custody.rs index 498c3d26..962b9c04 100644 --- a/crates/spt-store/src/resume_custody.rs +++ b/crates/spt-store/src/resume_custody.rs @@ -234,7 +234,11 @@ mod tests { let mut child = spawn_sleeper(); let pid = child.id(); mint(perch, pid).unwrap(); - assert_eq!(read_custody(perch), Custody::Ours(pid), "pair matches → OURS"); + assert_eq!( + read_custody(perch), + Custody::Ours(pid), + "pair matches → OURS" + ); assert!(resume_in_flight(perch)); clear(perch).unwrap(); @@ -348,7 +352,11 @@ mod tests { ) .unwrap(); - assert_eq!(read_custody(perch), Custody::None, "a bare pid is not custody"); + assert_eq!( + read_custody(perch), + Custody::None, + "a bare pid is not custody" + ); assert!( !perch.join(LEGACY_RESUME_PID_FILE).exists(), "and it is deleted on sight" diff --git a/crates/spt-store/src/roster.rs b/crates/spt-store/src/roster.rs index 6c9888c7..78d3900d 100644 --- a/crates/spt-store/src/roster.rs +++ b/crates/spt-store/src/roster.rs @@ -160,7 +160,8 @@ impl RosterStore { if let Some(parent) = path.parent() { std::fs::create_dir_all(parent).map_err(|e| RosterError::Io(e.to_string()))?; } - let json = serde_json::to_string_pretty(self).map_err(|e| RosterError::Io(e.to_string()))?; + let json = + serde_json::to_string_pretty(self).map_err(|e| RosterError::Io(e.to_string()))?; atomic_write_string(path, &json).map_err(|e| RosterError::Io(e.to_string())) } @@ -373,7 +374,10 @@ mod tests { #[test] fn merge_entry_is_strictly_greater_lease_wins() { let mut r = RosterStore::default(); - assert_eq!(r.merge_entry(entry("home", "aa", 5)), MergeOutcome::Inserted); + assert_eq!( + r.merge_entry(entry("home", "aa", 5)), + MergeOutcome::Inserted + ); // Lower lease loses (Stale) — the stored lease stays at 5. assert_eq!(r.merge_entry(entry("home", "aa", 3)), MergeOutcome::Stale); @@ -416,7 +420,11 @@ mod tests { "{pk} converges" ); } - assert_eq!(ab.find("home", "bb").unwrap().lease_epoch, 9, "newer bb wins"); + assert_eq!( + ab.find("home", "bb").unwrap().lease_epoch, + 9, + "newer bb wins" + ); // Idempotent: merging b again changes nothing. let before = ab.members.len(); @@ -447,7 +455,10 @@ mod tests { r.save_to(&path).unwrap(); let reloaded = RosterStore::load_from(&path); - assert!(reloaded.find("home", "offline").is_some(), "survives reload"); + assert!( + reloaded.find("home", "offline").is_some(), + "survives reload" + ); assert_eq!(reloaded.find("home", "online").unwrap().lease_epoch, 2); } @@ -479,7 +490,10 @@ mod tests { // Clears on re-pair: membership restored. assert!(r.clear_tombstone("home", "aa")); assert!(r.is_member("home", "aa"), "re-pair restores membership"); - assert!(!r.clear_tombstone("home", "aa"), "second clear is no-op false"); + assert!( + !r.clear_tombstone("home", "aa"), + "second clear is no-op false" + ); } // [unit->REQ-MESH-5] is_member_any: a node present in ≥1 subnet passes the @@ -542,7 +556,11 @@ mod tests { #[test] fn self_lease_ceiling_is_the_max_of_our_own_rows() { let mut r = RosterStore::default(); - assert_eq!(r.self_lease_ceiling("me"), 0, "the fleet holds nothing for us"); + assert_eq!( + r.self_lease_ceiling("me"), + 0, + "the fleet holds nothing for us" + ); r.upsert_self("home", "me", "l", "m", None, "1", 314_616); r.upsert_self("work", "me", "l", "m", None, "1", 803_460); // the frozen row @@ -555,7 +573,11 @@ mod tests { last_seen: "1".into(), lease_epoch: 999_999_999, // a peer's lease is not our ceiling }); - assert_eq!(r.self_lease_ceiling("me"), 803_460, "max over OUR rows only"); + assert_eq!( + r.self_lease_ceiling("me"), + 803_460, + "max over OUR rows only" + ); r.tombstone("work", "me", "9"); assert_eq!( diff --git a/crates/spt-store/src/rotation.rs b/crates/spt-store/src/rotation.rs index fdbba5cc..ad9fb67a 100644 --- a/crates/spt-store/src/rotation.rs +++ b/crates/spt-store/src/rotation.rs @@ -97,8 +97,8 @@ impl RotationPending { if let Some(parent) = path.parent() { std::fs::create_dir_all(parent)?; } - let json = serde_json::to_string_pretty(self) - .map_err(|e| std::io::Error::other(e.to_string()))?; + let json = + serde_json::to_string_pretty(self).map_err(|e| std::io::Error::other(e.to_string()))?; atomic_write_string(path, &json).map_err(std::io::Error::other) } @@ -229,7 +229,11 @@ mod tests { p.coalesce("now", &hexes(&["bb"]), 500); // force-rotate (deadline=now=500) assert_eq!(p.due_subnets(499), Vec::::new(), "nothing due yet"); - assert_eq!(p.due_subnets(500), vec!["now".to_string()], "force fires at deadline"); + assert_eq!( + p.due_subnets(500), + vec!["now".to_string()], + "force fires at deadline" + ); assert_eq!( p.due_subnets(1_000), vec!["home".to_string(), "now".to_string()], @@ -238,7 +242,11 @@ mod tests { assert!(p.clear("now")); assert!(!p.clear("now"), "second clear is a no-op false"); - assert_eq!(p.due_subnets(1_000), vec!["home".to_string()], "only home remains"); + assert_eq!( + p.due_subnets(1_000), + vec!["home".to_string()], + "only home remains" + ); } // The parked pending-admin-seed rules (ADR-0051 §2a): parking needs an @@ -267,10 +275,17 @@ mod tests { let path = dir.path().join("identity").join("rotation-pending.json"); p.save_to(&path).unwrap(); let back = RotationPending::load_from(&path); - assert_eq!(back.parked_admin("home"), Some(seed), "parked seed round-trips"); + assert_eq!( + back.parked_admin("home"), + Some(seed), + "parked seed round-trips" + ); p.subnets.get_mut("home").unwrap().pending_admin_hex = Some("zz".into()); - assert!(p.parked_admin("home").is_none(), "corrupt hex reads as absent"); + assert!( + p.parked_admin("home").is_none(), + "corrupt hex reads as absent" + ); } // [unit->REQ-MESH-4] the schedule round-trips atomically, and an absent or diff --git a/crates/spt-store/src/seal.rs b/crates/spt-store/src/seal.rs index 8eb6058b..87bcdf61 100644 --- a/crates/spt-store/src/seal.rs +++ b/crates/spt-store/src/seal.rs @@ -261,7 +261,10 @@ impl std::fmt::Display for SealMintError { match self { SealMintError::EmptyContent => write!(f, "refusing to seal empty content"), SealMintError::BadMinter(why) => { - write!(f, "minter must be fully qualified subnet:endpoint@node ({why})") + write!( + f, + "minter must be fully qualified subnet:endpoint@node ({why})" + ) } } } @@ -386,12 +389,17 @@ mod tests { assert!(!is_well_formed_token("2345678")); // 7: too short assert!(!is_well_formed_token("abcdefghjkm")); // 11: too long assert!(!is_well_formed_token("")); - for bad in ["0bcdefgh", "1bcdefgh", "ibcdefgh", "lbcdefgh", "obcdefgh", "ubcdefgh"] { + for bad in [ + "0bcdefgh", "1bcdefgh", "ibcdefgh", "lbcdefgh", "obcdefgh", "ubcdefgh", + ] { assert!(!is_well_formed_token(bad), "{bad} admitted"); } assert!(!is_well_formed_token("abc:defg"), "reserved delimiter"); assert!(!is_well_formed_token("abc@defg"), "reserved delimiter"); - assert!(!is_well_formed_token("ABCDEFGH"), "uppercase is not in the alphabet"); + assert!( + !is_well_formed_token("ABCDEFGH"), + "uppercase is not in the alphabet" + ); } // [unit->REQ-SEAL-RECORD] the mint seam: hash is the sha-256 of the exact diff --git a/crates/spt-store/src/sessions.rs b/crates/spt-store/src/sessions.rs index a30f620a..dfa1290a 100644 --- a/crates/spt-store/src/sessions.rs +++ b/crates/spt-store/src/sessions.rs @@ -423,11 +423,18 @@ mod tests { "the oldest survivor keeps its STAMPED ordinal (no renumber on prune)" ); let newest = rows.last().unwrap(); - assert_eq!(newest.ordinal, Some((n - 1) as u64), "newest keeps its stamp"); + assert_eq!( + newest.ordinal, + Some((n - 1) as u64), + "newest keeps its stamp" + ); // The whole survivor window is contiguous and monotonic. let ords: Vec = rows.iter().map(|e| e.ordinal.unwrap()).collect(); let expected: Vec = ((n - MAX_LEDGER) as u64..n as u64).collect(); - assert_eq!(ords, expected, "ordinals survive contiguous, never renumbered"); + assert_eq!( + ords, expected, + "ordinals survive contiguous, never renumbered" + ); } // [unit->REQ-DIGEST-CURSOR] a pre-migration ledger (rows with no `ordinal` key) diff --git a/crates/spt-store/src/shellinfo.rs b/crates/spt-store/src/shellinfo.rs index 37c3022c..8021dd12 100644 --- a/crates/spt-store/src/shellinfo.rs +++ b/crates/spt-store/src/shellinfo.rs @@ -523,7 +523,11 @@ mod tests { let live = online_perch(Some(&std::process::id().to_string())); assert!(!shell_pid_provably_dead(live.path())); - assert_eq!(status_of(&live), SHELL_STATUS_ONLINE, "a live pid is online"); + assert_eq!( + status_of(&live), + SHELL_STATUS_ONLINE, + "a live pid is online" + ); // The fail-toward-alive arms — none of these is EVIDENCE of a corpse. for (label, pid) in [ @@ -605,11 +609,17 @@ mod tests { assert_eq!(id0, "claude-spt-0", "id minted off the parent, no ':'"); assert!(!id0.contains(':'), "reserved delimiter never in the id"); let info0 = resolve_shell_ref(owlery, "doyle", &id0).unwrap().1; - assert_eq!(info0.adapter_name, "claude-spt:work", "composite carried verbatim"); + assert_eq!( + info0.adapter_name, "claude-spt:work", + "composite carried verbatim" + ); // A different profile of the SAME parent shares the ordinal space… let id1 = spawn(owlery, "doyle", "claude-spt:play", None); - assert_eq!(id1, "claude-spt-1", "profiles of one parent share -"); + assert_eq!( + id1, "claude-spt-1", + "profiles of one parent share -" + ); // …and a bare-parent spawn occupies the same space too. let id2 = spawn(owlery, "doyle", "claude-spt", None); assert_eq!(id2, "claude-spt-2"); diff --git a/crates/spt-store/src/spool.rs b/crates/spt-store/src/spool.rs index a777fda9..aba1c3fb 100644 --- a/crates/spt-store/src/spool.rs +++ b/crates/spt-store/src/spool.rs @@ -124,12 +124,13 @@ pub fn open_spool_at(perch_path: &Path) -> rusqlite::Result { // The `deferred` column is retained and kept in sync (deferred=1 IFF // window='active_only') so the existing deferred-keyed reads are unaffected. // `window` is a SQLite keyword (window functions) — always double-quoted in SQL. - let _ = conn - .execute_batch("ALTER TABLE messages ADD COLUMN \"window\" TEXT NOT NULL DEFAULT 'default'"); + let _ = conn.execute_batch( + "ALTER TABLE messages ADD COLUMN \"window\" TEXT NOT NULL DEFAULT 'default'", + ); let _ = conn.execute_batch("ALTER TABLE messages ADD COLUMN channel TEXT NOT NULL DEFAULT 'any'"); - let _ = conn - .execute_batch("ALTER TABLE messages ADD COLUMN ephemeral INTEGER NOT NULL DEFAULT 0"); + let _ = + conn.execute_batch("ALTER TABLE messages ADD COLUMN ephemeral INTEGER NOT NULL DEFAULT 0"); // W5 (REQ-SPOOL-TAKE-AUDIT) taker-audit columns — additive + NULLABLE (no schema // break; delivered rows are already retained, never deleted). Stamped in the SAME // UPDATE that flips `delivered = 1`, so a taken row records WHO took it: the leg @@ -260,7 +261,12 @@ pub struct TakerAudit { impl TakerAudit { /// A fresh audit stamp for `leg`, wall-clock `at_ms` set to now. pub fn new(leg: TakerLeg, sid: Option, pid: Option) -> Self { - Self { leg, sid, pid, at_ms: now_ms_u64() } + Self { + leg, + sid, + pid, + at_ms: now_ms_u64(), + } } } @@ -301,7 +307,10 @@ fn mark_delivered_audited( taken_pid = ?4, taken_at_ms = ?5 WHERE id = ?1", params![id, a.leg.as_str(), a.sid, a.pid, a.at_ms as i64], ), - None => conn.execute("UPDATE messages SET delivered = 1 WHERE id = ?1", params![id]), + None => conn.execute( + "UPDATE messages SET delivered = 1 WHERE id = ?1", + params![id], + ), } .map(|_| ()) } @@ -770,7 +779,11 @@ pub fn peek_non_deferred_at(perch_path: &Path) -> rusqlite::Result(0)?, row.get::<_, String>(1)?, row.get::<_, String>(2)?)) + Ok(( + row.get::<_, i64>(0)?, + row.get::<_, String>(1)?, + row.get::<_, String>(2)?, + )) })? .filter_map(|r| r.ok()) .collect(); @@ -940,8 +953,10 @@ mod tests { assert_eq!(dropped, 2, "both undelivered briefings, and only those"); let rows = audit_rows_at(p).unwrap(); - let survivors: Vec<(&str, bool)> = - rows.iter().map(|r| (r.from.as_str(), r.delivered)).collect(); + let survivors: Vec<(&str, bool)> = rows + .iter() + .map(|r| (r.from.as_str(), r.delivered)) + .collect(); assert!( survivors.contains(&("spt-engine-room", true)), "a DELIVERED row is history and survives the sweep: {survivors:?}" @@ -980,7 +995,11 @@ mod tests { spool_message_at(p, "bob", "unaudited").unwrap(); // Audited drain of the first row (relay-backlog leg with a sid + pid). - let audit = TakerAudit::new(TakerLeg::RelayBacklog, Some("sess-xyz".to_string()), Some(4242)); + let audit = TakerAudit::new( + TakerLeg::RelayBacklog, + Some("sess-xyz".to_string()), + Some(4242), + ); let got = drain_non_deferred_audited_at(p, &audit).unwrap(); assert_eq!(got.len(), 2, "both undelivered rows drain"); @@ -1004,7 +1023,10 @@ mod tests { let rows2 = audit_rows_at(p2).unwrap(); assert_eq!(rows2.len(), 1); assert!(rows2[0].delivered, "delivered flips"); - assert_eq!(rows2[0].taken_leg, None, "unaudited take stamps no provenance"); + assert_eq!( + rows2[0].taken_leg, None, + "unaudited take stamps no provenance" + ); assert_eq!(rows2[0].taken_pid, None); assert_eq!(rows2[0].taken_at_ms, None); } @@ -1296,9 +1318,11 @@ mod tests { let n = evaporate_ephemeral_non_deferred_at(p).unwrap(); assert_eq!(n, 2, "both ephemeral non-deferred rows evaporate"); - let remaining: Vec = - peek_all_at(p).unwrap().into_iter().map(|r| r.2).collect(); - assert!(remaining.contains(&"D-idle".to_string()), "durable idle row survives"); + let remaining: Vec = peek_all_at(p).unwrap().into_iter().map(|r| r.2).collect(); + assert!( + remaining.contains(&"D-idle".to_string()), + "durable idle row survives" + ); assert!( remaining.contains(&"E-act".to_string()), "ephemeral active_only (deferred) row survives evaporation (hook-channel persistence)" @@ -1333,7 +1357,10 @@ mod tests { // include_deferred: default + active_only, STILL never idle_only. let with_def = drain_active_window_at(p, true).unwrap(); let bodies: Vec<&str> = with_def.iter().map(|m| m.body.as_str()).collect(); - assert!(bodies.contains(&"A"), "active_only drains with include_deferred"); + assert!( + bodies.contains(&"A"), + "active_only drains with include_deferred" + ); assert!(bodies.contains(&"D2") && bodies.contains(&"A2")); assert!( !bodies.contains(&"I"), @@ -1367,7 +1394,10 @@ mod tests { let claimed = claim_idle_edge_at(p).unwrap(); assert_eq!( - claimed.iter().map(|(_, _, b)| b.as_str()).collect::>(), + claimed + .iter() + .map(|(_, _, b)| b.as_str()) + .collect::>(), vec!["D", "I"], "the idle edge claims non-deferred only, oldest-first — active_only is not offered" ); @@ -1404,7 +1434,10 @@ mod tests { // Idle-edge claims the row (take → delivered=1). let claimed = claim_idle_edge_at(p).unwrap(); assert_eq!( - claimed.iter().map(|(_, _, b)| b.as_str()).collect::>(), + claimed + .iter() + .map(|(_, _, b)| b.as_str()) + .collect::>(), vec!["D"] ); @@ -1421,7 +1454,10 @@ mod tests { // The hook-poll drain now sees it again — exactly once, id/body preserved. let redrained = drain_active_window_at(p, true).unwrap(); assert_eq!( - redrained.iter().map(|m| m.body.as_str()).collect::>(), + redrained + .iter() + .map(|m| m.body.as_str()) + .collect::>(), vec!["D"], "a released row surfaces again for a later drain (exactly once)" ); @@ -1659,7 +1695,10 @@ mod tests { let idle_audit2 = TakerAudit::new(TakerLeg::IdleInject, None, Some(2)); let claimed = claim_idle_edge_audited_at(p2, &idle_audit2).unwrap(); assert_eq!( - claimed.iter().map(|(_, _, b)| b.as_str()).collect::>(), + claimed + .iter() + .map(|(_, _, b)| b.as_str()) + .collect::>(), vec!["parked"], "an untaken parked row is still delivered by the idle-edge (F-023 class stays green)" ); diff --git a/crates/spt-store/src/subnet.rs b/crates/spt-store/src/subnet.rs index f084f9e2..0b61f56e 100644 --- a/crates/spt-store/src/subnet.rs +++ b/crates/spt-store/src/subnet.rs @@ -452,7 +452,10 @@ impl SubnetStore { // offliner still holds, and the rotator must be able to verify that // `N-1` proof to re-seed it across the rotation (Mesh-D7 grace). // [impl->REQ-MESH-4] - rec.prev_seed_hex = Some(std::mem::replace(&mut rec.seed_hex, encode_hex(&random_seed()))); + rec.prev_seed_hex = Some(std::mem::replace( + &mut rec.seed_hex, + encode_hex(&random_seed()), + )); // The admin half rotates in the SAME operation, under the SAME single // epoch bump — an admin key IS a membership key, so an eviction that // rotated only the member seed would leave the evicted node a rejoin @@ -683,12 +686,16 @@ mod tests { #[test] fn create_subnet_starts_at_epoch_one_unique_name() { let mut store = SubnetStore::default(); - let rec = store.create_subnet("home", crate::access::Mode::Open).expect("create"); + let rec = store + .create_subnet("home", crate::access::Mode::Open) + .expect("create"); assert_eq!(rec.epoch, 1); assert_eq!(rec.name, "home"); assert!(rec.seed_bytes().is_some(), "seed hex decodes to 20 bytes"); assert_eq!( - store.create_subnet("home", crate::access::Mode::Open).unwrap_err(), + store + .create_subnet("home", crate::access::Mode::Open) + .unwrap_err(), SubnetError::Exists("home".into()) ); } @@ -700,7 +707,10 @@ mod tests { #[test] fn rotate_bumps_epoch_and_changes_seed() { let mut store = SubnetStore::default(); - let before = store.create_subnet("home", crate::access::Mode::Open).expect("create").clone(); + let before = store + .create_subnet("home", crate::access::Mode::Open) + .expect("create") + .clone(); let after = store.rotate_seed("home", None).expect("rotate").clone(); assert_eq!(after.epoch, before.epoch + 1, "epoch bumps"); assert_ne!(after.seed_hex, before.seed_hex, "seed material rotates"); @@ -731,7 +741,10 @@ mod tests { #[test] fn adopt_rotation_takes_newer_seed_and_is_idempotent() { let mut store = SubnetStore::default(); - let before = store.create_subnet("home", crate::access::Mode::Open).expect("create").clone(); + let before = store + .create_subnet("home", crate::access::Mode::Open) + .expect("create") + .clone(); let new_seed = [0x5au8; TOTP_SEED_LEN]; // Stale node on epoch 1 adopts the rotator's epoch 2. @@ -746,8 +759,12 @@ mod tests { ); // A re-delivered (equal) or older push changes nothing. - assert!(!store.adopt_rotation("home", [0u8; TOTP_SEED_LEN], 2).expect("idem")); - assert!(!store.adopt_rotation("home", [0u8; TOTP_SEED_LEN], 1).expect("older")); + assert!(!store + .adopt_rotation("home", [0u8; TOTP_SEED_LEN], 2) + .expect("idem")); + assert!(!store + .adopt_rotation("home", [0u8; TOTP_SEED_LEN], 1) + .expect("older")); assert_eq!(store.find("home").unwrap().seed_bytes(), Some(new_seed)); assert_eq!( @@ -771,11 +788,21 @@ mod tests { .create_subnet("home", crate::access::Mode::Open) .expect("create") .clone(); - let old_admin_hex = before.admin_seed_hex.clone().expect("minted with admin key"); + let old_admin_hex = before + .admin_seed_hex + .clone() + .expect("minted with admin key"); let pending = [0x42u8; TOTP_SEED_LEN]; - let after = store.rotate_seed("home", Some(pending)).expect("rotate").clone(); - assert_eq!(after.epoch, before.epoch + 1, "exactly one epoch bump for both seeds"); + let after = store + .rotate_seed("home", Some(pending)) + .expect("rotate") + .clone(); + assert_eq!( + after.epoch, + before.epoch + 1, + "exactly one epoch bump for both seeds" + ); assert_eq!( after.admin_seed_bytes(), Some(pending), @@ -811,7 +838,10 @@ mod tests { .expect("create") .clone(); let after = store.rotate_seed("home", None).expect("rotate").clone(); - assert_ne!(after.seed_hex, before.seed_hex, "member seed rotates regardless"); + assert_ne!( + after.seed_hex, before.seed_hex, + "member seed rotates regardless" + ); assert_eq!(after.epoch, 2, "epoch bumps regardless"); assert_eq!( after.admin_seed_hex, before.admin_seed_hex, @@ -846,7 +876,9 @@ mod tests { let pushed = [0x7bu8; TOTP_SEED_LEN]; // Current epoch (1) adopts. - assert!(store.adopt_admin_rotation("home", pushed, 1).expect("adopt")); + assert!(store + .adopt_admin_rotation("home", pushed, 1) + .expect("adopt")); assert_eq!( store.find("home").unwrap().admin_seed_bytes(), Some(pushed), @@ -871,7 +903,9 @@ mod tests { .find(|s| s.name == "home") .unwrap() .admin_seed_hex = None; - assert!(store.adopt_admin_rotation("home", pushed, 5).expect("re-provision")); + assert!(store + .adopt_admin_rotation("home", pushed, 5) + .expect("re-provision")); assert_eq!(store.find("home").unwrap().admin_seed_bytes(), Some(pushed)); assert_eq!( @@ -917,8 +951,13 @@ mod tests { #[test] fn no_prior_generation_before_rotation() { let mut store = SubnetStore::default(); - let rec = store.create_subnet("home", crate::access::Mode::Open).expect("create"); - assert!(rec.prev_seed_hex.is_none(), "fresh subnet has no prior seed"); + let rec = store + .create_subnet("home", crate::access::Mode::Open) + .expect("create"); + assert!( + rec.prev_seed_hex.is_none(), + "fresh subnet has no prior seed" + ); assert!(rec.prev_seed_bytes().is_none()); } @@ -966,8 +1005,12 @@ mod tests { let path = dir.path().join("identity").join("subnet.json"); let mut store = SubnetStore::default(); - store.create_subnet("home", crate::access::Mode::Open).unwrap(); - store.create_subnet("work", crate::access::Mode::Open).unwrap(); + store + .create_subnet("home", crate::access::Mode::Open) + .unwrap(); + store + .create_subnet("work", crate::access::Mode::Open) + .unwrap(); store.rotate_seed("home", None).unwrap(); store.save_to(&path).unwrap(); @@ -987,7 +1030,10 @@ mod tests { fn hide_new_endpoints_defaults_off_and_persists() { let mut store = SubnetStore::default(); assert!( - !store.create_subnet("home", crate::access::Mode::Open).unwrap().hide_new_endpoints, + !store + .create_subnet("home", crate::access::Mode::Open) + .unwrap() + .hide_new_endpoints, "ships OFF" ); @@ -1035,7 +1081,9 @@ mod tests { #[test] fn remove_drops_membership() { let mut store = SubnetStore::default(); - store.create_subnet("home", crate::access::Mode::Open).unwrap(); + store + .create_subnet("home", crate::access::Mode::Open) + .unwrap(); assert!(store.remove("home")); assert!(!store.remove("home"), "second remove is a no-op false"); assert!(store.find("home").is_none()); @@ -1047,8 +1095,16 @@ mod tests { fn minted_seeds_are_random() { let mut a = SubnetStore::default(); let mut b = SubnetStore::default(); - let sa = a.create_subnet("x", crate::access::Mode::Open).unwrap().seed_hex.clone(); - let sb = b.create_subnet("x", crate::access::Mode::Open).unwrap().seed_hex.clone(); + let sa = a + .create_subnet("x", crate::access::Mode::Open) + .unwrap() + .seed_hex + .clone(); + let sb = b + .create_subnet("x", crate::access::Mode::Open) + .unwrap() + .seed_hex + .clone(); assert_ne!(sa, sb); } @@ -1101,7 +1157,9 @@ mod tests { assert!(rec.mode.is_none(), "no posture is invented"); let mut store = SubnetStore::default(); - let joined = store.add_joined("work", [7u8; TOTP_SEED_LEN], 5, None, None).expect("join"); + let joined = store + .add_joined("work", [7u8; TOTP_SEED_LEN], 5, None, None) + .expect("join"); assert!(joined.admin_seed_hex.is_none()); assert!(joined.mode.is_none()); } diff --git a/crates/spt-store/src/trustwarn.rs b/crates/spt-store/src/trustwarn.rs index be4fd977..1e24bb0b 100644 --- a/crates/spt-store/src/trustwarn.rs +++ b/crates/spt-store/src/trustwarn.rs @@ -255,9 +255,8 @@ pub fn compose_trust_warning(peer: &WarnedPeer, custom: Option<&str>) -> String // mapping rather than a fourth spelling of it. "Once you have decided what they are to you, record it and this warning stops: \ {}\n", - crate::monic::classify_add_command(id, "").unwrap_or_else( - || "spt endpoint monic add --help".to_string() - ) + crate::monic::classify_add_command(id, "") + .unwrap_or_else(|| "spt endpoint monic add --help".to_string()) )), // Honest about the dead end rather than printing a command that cannot // work: a monic is about an endpoint, and there is no endpoint id here @@ -468,7 +467,10 @@ mod tests { let dir = tempfile::tempdir().unwrap(); let d = dir.path(); set_override_at(d, "todlando", "todlando's rule").unwrap(); - assert_eq!(override_at(d, "todlando").as_deref(), Some("todlando's rule")); + assert_eq!( + override_at(d, "todlando").as_deref(), + Some("todlando's rule") + ); assert_eq!(override_at(d, "doyle"), None); } @@ -489,7 +491,10 @@ mod tests { &WarnedPeer::Endpoint("stranger".into()), override_at(d, id).as_deref(), ); - assert!(w.contains("do not hand over secrets"), "default advisory: {w}"); + assert!( + w.contains("do not hand over secrets"), + "default advisory: {w}" + ); } } @@ -504,7 +509,10 @@ mod tests { std::fs::write(d.join("outside"), "planted text").unwrap(); for bad in ["../outside", "a/b", ""] { assert_eq!(override_at(d, bad), None, "{bad} must not read"); - assert!(set_override_at(d, bad, "text").is_err(), "{bad} must not write"); + assert!( + set_override_at(d, bad, "text").is_err(), + "{bad} must not write" + ); assert!(clear_override_at(d, bad).is_err(), "{bad} must not delete"); } assert!(d.join("outside").is_file(), "nothing outside was touched"); @@ -533,7 +541,11 @@ mod tests { let dir = tempfile::tempdir().unwrap(); assert!(set_override_at(dir.path(), "todlando", " ").is_err()); assert!(set_override_at(dir.path(), "todlando", &long).is_err()); - assert_eq!(override_at(dir.path(), "todlando"), None, "neither was stored"); + assert_eq!( + override_at(dir.path(), "todlando"), + None, + "neither was stored" + ); } // [unit->REQ-TRUST-WARNING-OVERRIDE] the scope the verb must state is the @@ -559,7 +571,10 @@ mod tests { !w.contains("monic add"), "no classify command, because there is nobody to classify: {w}" ); - assert!(w.contains("spt endpoint access"), "the real way out is named: {w}"); + assert!( + w.contains("spt endpoint access"), + "the real way out is named: {w}" + ); assert!(w.contains("node aa11bb22 at all")); } @@ -661,7 +676,10 @@ mod tests { let same = "aa11bb22"; claim_warned_at(&session, &WarnedPeer::UnnamedOn(same.to_string())); - assert!(!warning_owed_at(&session, &WarnedPeer::UnnamedOn(same.to_string()))); + assert!(!warning_owed_at( + &session, + &WarnedPeer::UnnamedOn(same.to_string()) + )); assert!( warning_owed_at(&session, &endpoint(same)), "an endpoint id spelled like the node key is a different peer" @@ -738,7 +756,10 @@ mod tests { WarnedPeer::UnnamedOn("../../escape".to_string()), WarnedPeer::UnnamedOn(String::new()), ] { - assert!(warning_owed_at(&session, &peer), "{peer:?} warns before any claim"); + assert!( + warning_owed_at(&session, &peer), + "{peer:?} warns before any claim" + ); claim_warned_at(&session, &peer); assert!( warning_owed_at(&session, &peer), diff --git a/crates/spt-store/src/worker_reap.rs b/crates/spt-store/src/worker_reap.rs index 80d5b7ee..30f98a82 100644 --- a/crates/spt-store/src/worker_reap.rs +++ b/crates/spt-store/src/worker_reap.rs @@ -57,8 +57,19 @@ pub fn now_secs() -> u64 { /// Reap a parent's REAPABLE nested WORKER perches against the process-global owlery. // [impl->REQ-WORKER-REAP] -pub fn reap_workers(parent_id: &str, parent_alive: bool, ttl_secs: u64, now_secs: u64) -> Vec { - reap_workers_in(&perch::owlery_dir(), parent_id, parent_alive, ttl_secs, now_secs) +pub fn reap_workers( + parent_id: &str, + parent_alive: bool, + ttl_secs: u64, + now_secs: u64, +) -> Vec { + reap_workers_in( + &perch::owlery_dir(), + parent_id, + parent_alive, + ttl_secs, + now_secs, + ) } /// [`reap_workers`] against an explicit owlery root. @@ -111,7 +122,11 @@ pub fn reap_workers_in( } let ready = child.join("ready").exists(); // Age drives BOTH the TTL floor and the orphan boot-race grace. - let age = rec.started.parse::().ok().map(|s| now_secs.saturating_sub(s)); + let age = rec + .started + .parse::() + .ok() + .map(|s| now_secs.saturating_sub(s)); let expired = ttl_secs > 0 && matches!(age, Some(a) if a > ttl_secs); let young = matches!(age, Some(a) if a < ORPHAN_GRACE_SECS); let pending = spool::pending_count_at(&child).unwrap_or(0); @@ -140,14 +155,28 @@ mod tests { fn establish_parent(owlery: &Path, id: &str) { let p = perch::resolve_perch_path_in(owlery, id, ParentHint::Infer); std::fs::create_dir_all(&p).unwrap(); - info::write_info(&p, &InfoJson::new(id, "0", std::process::id(), "psid", "live_agent")).unwrap(); + info::write_info( + &p, + &InfoJson::new(id, "0", std::process::id(), "psid", "live_agent"), + ) + .unwrap(); } /// Seed a worker perch with a controllable `started` (epoch secs) + ready marker. - fn seed_worker(owlery: &Path, parent: &str, wid: &str, started: u64, ready: bool) -> std::path::PathBuf { + fn seed_worker( + owlery: &Path, + parent: &str, + wid: &str, + started: u64, + ready: bool, + ) -> std::path::PathBuf { let p = perch::resolve_perch_path_in(owlery, wid, ParentHint::Explicit(parent)); std::fs::create_dir_all(&p).unwrap(); - info::write_info(&p, &InfoJson::new(wid, &started.to_string(), 2_000_000_000, "psid", "worker")).unwrap(); + info::write_info( + &p, + &InfoJson::new(wid, &started.to_string(), 2_000_000_000, "psid", "worker"), + ) + .unwrap(); if ready { std::fs::write(p.join("ready"), "").unwrap(); } @@ -165,7 +194,11 @@ mod tests { #[test] fn clamp_ttl_floors_fat_finger_but_allows_disable() { assert_eq!(clamp_reap_ttl(0), 0, "0 = explicit disable"); - assert_eq!(clamp_reap_ttl(10), MIN_REAP_TTL_SECS, "a fat-fingered 10s is floored"); + assert_eq!( + clamp_reap_ttl(10), + MIN_REAP_TTL_SECS, + "a fat-fingered 10s is floored" + ); assert_eq!(clamp_reap_ttl(MIN_REAP_TTL_SECS - 1), MIN_REAP_TTL_SECS); assert_eq!(clamp_reap_ttl(7_200), 7_200, "a sane value passes through"); } @@ -185,7 +218,10 @@ mod tests { assert_eq!(reaped, vec!["alice-w2".to_string()]); assert!(exists(o.path(), "alice-w1"), "in-flight kept"); assert!(!exists(o.path(), "alice-w2"), "drained soft-stop reaped"); - assert!(exists(o.path(), "alice-w3"), "pending results kept (awaiting drain)"); + assert!( + exists(o.path(), "alice-w3"), + "pending results kept (awaiting drain)" + ); } // [unit->REQ-WORKER-REAP] ORPHANED (parent not alive): an aged worker reaps; a @@ -194,13 +230,22 @@ mod tests { fn orphaned_respects_boot_race_grace() { let o = owlery(); establish_parent(o.path(), "alice"); - seed_worker(o.path(), "alice", "alice-w1", NOW - (ORPHAN_GRACE_SECS + 30), true); // aged + seed_worker( + o.path(), + "alice", + "alice-w1", + NOW - (ORPHAN_GRACE_SECS + 30), + true, + ); // aged seed_worker(o.path(), "alice", "alice-w2", NOW - 5, true); // young let reaped = reap_workers_in(o.path(), "alice", false, TTL, NOW); assert_eq!(reaped, vec!["alice-w1".to_string()]); assert!(!exists(o.path(), "alice-w1"), "an aged orphan reaps"); - assert!(exists(o.path(), "alice-w2"), "a just-started worker survives the boot-race grace"); + assert!( + exists(o.path(), "alice-w2"), + "a just-started worker survives the boot-race grace" + ); } // [unit->REQ-WORKER-REAP] the TTL floor OVERRIDES a live ready marker DELIBERATELY @@ -214,11 +259,20 @@ mod tests { let reaped = reap_workers_in(o.path(), "alice", true, TTL, NOW); assert_eq!(reaped, vec!["alice-w1".to_string()]); - assert!(!exists(o.path(), "alice-w1"), "expired ready worker reaps (TTL overrides ready)"); - assert!(exists(o.path(), "alice-w2"), "fresh ready worker under a live parent stays"); + assert!( + !exists(o.path(), "alice-w1"), + "expired ready worker reaps (TTL overrides ready)" + ); + assert!( + exists(o.path(), "alice-w2"), + "fresh ready worker under a live parent stays" + ); seed_worker(o.path(), "alice", "alice-w3", NOW - (TTL + 100), true); - assert!(reap_workers_in(o.path(), "alice", true, 0, NOW).is_empty(), "ttl=0 disables"); + assert!( + reap_workers_in(o.path(), "alice", true, 0, NOW).is_empty(), + "ttl=0 disables" + ); assert!(exists(o.path(), "alice-w3")); } @@ -227,15 +281,25 @@ mod tests { fn never_touches_a_psyche() { let o = owlery(); establish_parent(o.path(), "alice"); - let psyche = perch::resolve_perch_path_in(o.path(), "alice-psyche", ParentHint::Explicit("alice")); + let psyche = + perch::resolve_perch_path_in(o.path(), "alice-psyche", ParentHint::Explicit("alice")); std::fs::create_dir_all(&psyche).unwrap(); info::write_info( &psyche, - &InfoJson::new("alice-psyche", &(NOW - 999_999).to_string(), 2_000_000_000, "psid", "psyche"), + &InfoJson::new( + "alice-psyche", + &(NOW - 999_999).to_string(), + 2_000_000_000, + "psid", + "psyche", + ), ) .unwrap(); assert!(reap_workers_in(o.path(), "alice", false, TTL, NOW).is_empty()); - assert!(psyche.join("info.json").exists(), "the nested psyche survives the worker GC"); + assert!( + psyche.join("info.json").exists(), + "the nested psyche survives the worker GC" + ); } // [unit->REQ-WORKER-REAP] the WIRED-reap twin of worker_seq::counter_survives_reap: diff --git a/crates/spt-store/src/worker_seq.rs b/crates/spt-store/src/worker_seq.rs index 14c599e7..918cb2a8 100644 --- a/crates/spt-store/src/worker_seq.rs +++ b/crates/spt-store/src/worker_seq.rs @@ -128,7 +128,11 @@ mod tests { } let ids: Vec = handles.into_iter().map(|h| h.join().unwrap()).collect(); let unique: HashSet<&String> = ids.iter().collect(); - assert_eq!(unique.len(), N, "every concurrent mint must be a distinct id"); + assert_eq!( + unique.len(), + N, + "every concurrent mint must be a distinct id" + ); // The set is exactly {alice-w1 .. alice-wN} — contiguous, no gap, no dupe. for n in 1..=N { assert!( diff --git a/crates/spt-store/src/wtlock.rs b/crates/spt-store/src/wtlock.rs index 3c9080bb..1d7f407a 100644 --- a/crates/spt-store/src/wtlock.rs +++ b/crates/spt-store/src/wtlock.rs @@ -225,7 +225,10 @@ mod tests { msg.contains(&sentinel.display().to_string()), "refusal must name the sentinel path: {msg}" ); - assert!(msg.contains("bound 120ms"), "refusal must name the bound: {msg}"); + assert!( + msg.contains("bound 120ms"), + "refusal must name the bound: {msg}" + ); assert!( msg.contains("after ") && msg.contains("ms ("), "refusal must name the ELAPSED wait beside the bound: {msg}" diff --git a/crates/spt-store/tests/carrier_claim_int.rs b/crates/spt-store/tests/carrier_claim_int.rs index d4f3c8d5..5d053c75 100644 --- a/crates/spt-store/tests/carrier_claim_int.rs +++ b/crates/spt-store/tests/carrier_claim_int.rs @@ -117,20 +117,21 @@ fn two_carriers_race_one_spool_every_row_delivered_exactly_once() { let mut taken: Vec = Vec::new(); let deadline = Instant::now() + Duration::from_secs(30); loop { - let audit = - TakerAudit::new(leg, Some(format!("sid-{}", leg.as_str())), Some(std::process::id())); + let audit = TakerAudit::new( + leg, + Some(format!("sid-{}", leg.as_str())), + Some(std::process::id()), + ); // A DatabaseBusy take is an EXPECTED adversarial-contention outcome // (busy budget exhausted; delivered=0 untouched → safe retry), NOT an // invariant breach — yield+retry under the same deadline guard. let batch: Vec = match leg { - TakerLeg::HookPoll => { - retrying_busy(deadline, leg.as_str(), || { - drain_active_window_audited_at(&cp, false, &audit) - }) - .into_iter() - .map(|m| m.body) - .collect() - } + TakerLeg::HookPoll => retrying_busy(deadline, leg.as_str(), || { + drain_active_window_audited_at(&cp, false, &audit) + }) + .into_iter() + .map(|m| m.body) + .collect(), _ => retrying_busy(deadline, leg.as_str(), || { claim_idle_edge_audited_at(&cp, &audit) }) @@ -189,5 +190,8 @@ fn two_carriers_race_one_spool_every_row_delivered_exactly_once() { let expected: HashSet = (0..N).map(|i| format!("msg-{i}")).collect(); let got: HashSet = all.into_iter().collect(); - assert_eq!(got, expected, "the exact produced set was delivered, nothing else"); + assert_eq!( + got, expected, + "the exact produced set was delivered, nothing else" + ); } diff --git a/crates/spt-store/tests/wtlock_two_process_int.rs b/crates/spt-store/tests/wtlock_two_process_int.rs index 5121fb56..0058c345 100644 --- a/crates/spt-store/tests/wtlock_two_process_int.rs +++ b/crates/spt-store/tests/wtlock_two_process_int.rs @@ -47,7 +47,9 @@ fn shared_worktree(root: &Path) -> (BranchStore, PathBuf, PathBuf) { let git_dir = root.join("seed.git"); let store = BranchStore::open_or_init(&git_dir).expect("bare store"); let wt = root.join("projects").join("p-rig"); - store.ensure_worktree("p-rig", &wt).expect("linked worktree"); + store + .ensure_worktree("p-rig", &wt) + .expect("linked worktree"); (store, git_dir, wt) } @@ -200,7 +202,10 @@ fn an_acquire_waits_out_a_holder_in_another_process_then_succeeds() { .next() .expect("holder must announce HELD") .expect("holder stdout line"); - assert!(held.starts_with("HELD "), "unexpected holder output: {held}"); + assert!( + held.starts_with("HELD "), + "unexpected holder output: {held}" + ); let held_at = Instant::now(); let started = Instant::now(); diff --git a/crates/spt-term/src/lib.rs b/crates/spt-term/src/lib.rs index 8c18cd29..4ac7ea87 100644 --- a/crates/spt-term/src/lib.rs +++ b/crates/spt-term/src/lib.rs @@ -45,12 +45,12 @@ pub mod surface; mod winprog; pub use digest::{Digest, DigestConfig, DigestEntry, ToolUse, Turn}; +pub use portable_pty::CommandBuilder; pub use projection::{ parse_context_record, project, project_lines, project_lines_diagnosed, project_timeline, record_to_tagged, record_to_tagged_result, window_input_turns, ContextRecord, DigestDiagnostics, DigestRecord, DigestRole, DropReason, DroppedLine, TimelineItem, ToolRef, }; -pub use portable_pty::CommandBuilder; pub use pty::PtySession; pub use reader::Drain; // [impl->REQ-BROKER-SCREEN-GRID] the server-side render grid + clean repaint on diff --git a/crates/spt-term/src/projection.rs b/crates/spt-term/src/projection.rs index 1fb75acd..fb783b0d 100644 --- a/crates/spt-term/src/projection.rs +++ b/crates/spt-term/src/projection.rs @@ -304,10 +304,7 @@ pub enum TimelineItem { /// (REQ-DIGEST-CURSOR) — `(ledger_ordinal << 32) | per_session_line_idx`, /// computed by the daemon when it builds the timeline. The seq is the stable /// cursor key threaded onto the folded entry/turn. - Activity { - record: DigestRecord, - seq: u64, - }, + Activity { record: DigestRecord, seq: u64 }, /// An spt-injected context entry (`kind`, `body`, `ts`). Context { kind: String, @@ -548,7 +545,10 @@ mod tests { assert_eq!(d.turns.len(), 1); let t = &d.turns[0]; assert_eq!(t.input.as_deref(), Some("add a file")); - assert_eq!(t.entries[0], DigestEntry::agent("sure, doing it".to_string())); + assert_eq!( + t.entries[0], + DigestEntry::agent("sure, doing it".to_string()) + ); match &t.entries[1] { DigestEntry::ToolSprint { tools: s, .. } => { assert_eq!(s.len(), 2, "consecutive tools collapse into one sprint"); @@ -618,7 +618,10 @@ mod tests { }) .expect("a sprint"); assert_eq!(sprint[0].name, "Bash"); - assert_eq!(sprint[0].arg, "this-is-a-…", "arg truncated to width with ellipsis"); + assert_eq!( + sprint[0].arg, "this-is-a-…", + "arg truncated to width with ellipsis" + ); } // [unit->REQ-TERM-4] forward-compat: a malformed line, an unknown role, and a @@ -662,7 +665,10 @@ mod tests { let d = project_lines(lines, &cfg(3)); assert_eq!(d.turns.len(), 2); assert_eq!(d.turns[0].input, None, "preamble turn has no input"); - assert_eq!(d.turns[0].entries[0], DigestEntry::agent("booting".to_string())); + assert_eq!( + d.turns[0].entries[0], + DigestEntry::agent("booting".to_string()) + ); assert_eq!(d.turns[1].input.as_deref(), Some("first")); } @@ -734,10 +740,9 @@ mod tests { // absent — backward-compat with pre-ADR-0019 records that carry no timestamp. #[test] fn ts_ordering_key_parses_and_is_optional() { - let with_ts = record_to_tagged( - r#"{"role":"input","text":"hi","ts":"2026-06-13T21:00:00Z"}"#, - ) - .expect("a valid record"); + let with_ts = + record_to_tagged(r#"{"role":"input","text":"hi","ts":"2026-06-13T21:00:00Z"}"#) + .expect("a valid record"); assert_eq!(with_ts.ts.as_deref(), Some("2026-06-13T21:00:00Z")); let without_ts = record_to_tagged(r#"{"role":"agent","text":"no clock"}"#).expect("a valid record"); @@ -820,11 +825,15 @@ mod tests { ]; let d = project_timeline(&items, &cfg(3)); let inputs: Vec<_> = d.turns.iter().filter_map(|t| t.input.as_deref()).collect(); - assert_eq!(inputs, vec!["before", "after"], "window bridges the boundary"); - assert!(d - .turns + assert_eq!( + inputs, + vec!["before", "after"], + "window bridges the boundary" + ); + assert!(d.turns.iter().any(|t| t + .entries .iter() - .any(|t| t.entries.iter().any(|e| matches!(e, DigestEntry::Boundary { .. })))); + .any(|e| matches!(e, DigestEntry::Boundary { .. })))); } // [unit->REQ-TERM-6] window_input_turns counts only input-bearing turns, keeps @@ -848,10 +857,9 @@ mod tests { let win = window_input_turns(vec![t("a"), t("b"), bound(), t("c")], 2); let inputs: Vec<_> = win.iter().filter_map(|x| x.input.as_deref()).collect(); assert_eq!(inputs, vec!["b", "c"]); - assert!(win.iter().any(|x| matches!( - x.entries.first(), - Some(DigestEntry::Boundary { .. }) - ))); + assert!(win + .iter() + .any(|x| matches!(x.entries.first(), Some(DigestEntry::Boundary { .. })))); // window 1 orphans the leading divider → trimmed. let win = window_input_turns(vec![t("a"), bound(), t("c")], 1); assert_eq!(win.len(), 1); @@ -889,10 +897,16 @@ mod tests { } for e in &t.entries { match e { - DigestEntry::Agent { text, seq: Some(s), .. } => { + DigestEntry::Agent { + text, seq: Some(s), .. + } => { out.push((format!("agent:{text}"), *s)); } - DigestEntry::ToolSprint { tools, seq: Some(s), .. } => { + DigestEntry::ToolSprint { + tools, + seq: Some(s), + .. + } => { out.push((format!("tools:{}", tools.len()), *s)); } _ => {} @@ -923,7 +937,9 @@ mod tests { let before_committed = committed_seqs(&before); // t2 is the trailing OPEN turn → partial, no committed seqs; t0/t1 committed. assert!( - before_committed.iter().any(|(k, s)| k == "input:t1" && *s == 200), + before_committed + .iter() + .any(|(k, s)| k == "input:t1" && *s == 200), "t1 is committed with its source seq before the slide: {before_committed:?}" ); @@ -932,8 +948,16 @@ mod tests { extended.push(act_seq(DigestRole::Input, "t3", 400)); extended.push(act_seq(DigestRole::Agent, "r3", 401)); let after = project_timeline(&extended, &cfg(3)); - let inputs: Vec<_> = after.turns.iter().filter_map(|t| t.input.as_deref()).collect(); - assert_eq!(inputs, vec!["t1", "t2", "t3"], "the window slid: t0 dropped"); + let inputs: Vec<_> = after + .turns + .iter() + .filter_map(|t| t.input.as_deref()) + .collect(); + assert_eq!( + inputs, + vec!["t1", "t2", "t3"], + "the window slid: t0 dropped" + ); // Every committed entry present in BOTH projections has the SAME seq. let after_committed = committed_seqs(&after); @@ -947,10 +971,16 @@ mod tests { } // Concretely: t1's input + reply kept their source seqs (200/201) even though // t1 moved from window-index 1 to window-index 0 under the slide. - assert!(after_committed.iter().any(|(k, s)| k == "input:t1" && *s == 200)); - assert!(after_committed.iter().any(|(k, s)| k == "agent:r1" && *s == 201)); + assert!(after_committed + .iter() + .any(|(k, s)| k == "input:t1" && *s == 200)); + assert!(after_committed + .iter() + .any(|(k, s)| k == "agent:r1" && *s == 201)); // And t2 (open before) is now committed with its OWN original source seqs. - assert!(after_committed.iter().any(|(k, s)| k == "input:t2" && *s == 300)); + assert!(after_committed + .iter() + .any(|(k, s)| k == "input:t2" && *s == 300)); } // [unit->REQ-DIGEST-CURSOR] seq encoding ordering at the daemon's @@ -996,11 +1026,21 @@ mod tests { "the collapsed sprint carries its LAST record's seq (12, not 11)" ); // Sanity: the partial single-turn projection blanked the sprint seq. - let partial_sprint = d.turns.last().unwrap().entries.iter().find_map(|e| match e { - DigestEntry::ToolSprint { seq, .. } => Some(*seq), - _ => None, - }); - assert_eq!(partial_sprint, Some(None), "the open turn's sprint seq is blanked"); + let partial_sprint = d + .turns + .last() + .unwrap() + .entries + .iter() + .find_map(|e| match e { + DigestEntry::ToolSprint { seq, .. } => Some(*seq), + _ => None, + }); + assert_eq!( + partial_sprint, + Some(None), + "the open turn's sprint seq is blanked" + ); } // [unit->REQ-DIGEST-CURSOR] the trailing OPEN turn is partial:true with NO seqs @@ -1074,12 +1114,27 @@ mod tests { #[test] fn idle_seals_the_trailing_turn_while_busy_leaves_it_partial() { let items = finished_turn_timeline(); - let busy = project_timeline(&items, &DigestConfig { endpoint_idle: false, ..cfg(3) }); - let idle = project_timeline(&items, &DigestConfig { endpoint_idle: true, ..cfg(3) }); + let busy = project_timeline( + &items, + &DigestConfig { + endpoint_idle: false, + ..cfg(3) + }, + ); + let idle = project_timeline( + &items, + &DigestConfig { + endpoint_idle: true, + ..cfg(3) + }, + ); // BUSY: today's behavior, unchanged. assert_eq!(busy.turns.len(), 2); - assert!(busy.turns[1].partial, "a busy endpoint's trailing turn stays partial"); + assert!( + busy.turns[1].partial, + "a busy endpoint's trailing turn stays partial" + ); assert_eq!( trailing_seqs(&busy), (None, None), @@ -1120,13 +1175,22 @@ mod tests { fn the_sealed_seq_equals_what_the_next_input_fallback_would_assign() { let idle = project_timeline( &finished_turn_timeline(), - &DigestConfig { endpoint_idle: true, ..cfg(3) }, + &DigestConfig { + endpoint_idle: true, + ..cfg(3) + }, ); // The fallback shape: the owner WAS prompted again, so the turn closed // structurally — still busy, no idle signal needed. let mut prompted = finished_turn_timeline(); prompted.push(act_seq(DigestRole::Input, "next ask", 70)); - let fallback = project_timeline(&prompted, &DigestConfig { endpoint_idle: false, ..cfg(3) }); + let fallback = project_timeline( + &prompted, + &DigestConfig { + endpoint_idle: false, + ..cfg(3) + }, + ); let sealed = idle.turns.last().expect("the sealed turn"); let closed = &fallback.turns[1]; // same turn, closed by the later input @@ -1146,10 +1210,16 @@ mod tests { #[test] fn re_projecting_a_sealed_idle_timeline_is_identical() { let items = finished_turn_timeline(); - let cfg = DigestConfig { endpoint_idle: true, ..cfg(3) }; + let cfg = DigestConfig { + endpoint_idle: true, + ..cfg(3) + }; let first = project_timeline(&items, &cfg); let second = project_timeline(&items, &cfg); - assert_eq!(first, second, "seal is idempotent — a re-pull is byte-identical"); + assert_eq!( + first, second, + "seal is idempotent — a re-pull is byte-identical" + ); // And spelled out at the level a consumer keys on, so a future regression // names the seq rather than dumping a whole struct diff. assert_eq!(trailing_seqs(&first), trailing_seqs(&second)); @@ -1163,10 +1233,17 @@ mod tests { // may add rows past a poller's cursor, never renumber rows behind it. #[test] fn a_post_seal_straggler_folds_in_without_moving_a_published_seq() { - let cfg = DigestConfig { endpoint_idle: true, ..cfg(3) }; + let cfg = DigestConfig { + endpoint_idle: true, + ..cfg(3) + }; let before = project_timeline(&finished_turn_timeline(), &cfg); let published = trailing_seqs(&before); - assert_eq!(published, (Some(60), Some(61)), "PRECONDITION: the seal published 60/61"); + assert_eq!( + published, + (Some(60), Some(61)), + "PRECONDITION: the seal published 60/61" + ); // The straggler: a later agent line flushed after the idle report. Higher // line index ⇒ higher seq, by construction. @@ -1175,8 +1252,15 @@ mod tests { let after = project_timeline(&late, &cfg); let sealed = after.turns.last().expect("still one trailing turn"); - assert_eq!(after.turns.len(), 2, "the straggler folded IN — it did not open a turn"); - assert!(!sealed.partial, "the turn stays sealed (the endpoint is still idle)"); + assert_eq!( + after.turns.len(), + 2, + "the straggler folded IN — it did not open a turn" + ); + assert!( + !sealed.partial, + "the turn stays sealed (the endpoint is still idle)" + ); assert_eq!( trailing_seqs(&after), published, @@ -1184,7 +1268,12 @@ mod tests { ); // The straggler is visible, past the published cursor — a poller at 61 sees // exactly the new row and nothing it already read. - assert_eq!(sealed.entries.len(), 2, "the late row is present: {:?}", sealed.entries); + assert_eq!( + sealed.entries.len(), + 2, + "the late row is present: {:?}", + sealed.entries + ); assert!( matches!(&sealed.entries[1], DigestEntry::Agent { text, seq: Some(62), .. } if text == "…and pushed the tag"), @@ -1200,7 +1289,10 @@ mod tests { // phantom sealed turn), and a single finished turn seals as the only turn. #[test] fn idle_on_an_empty_or_single_turn_timeline_invents_nothing() { - let cfg = DigestConfig { endpoint_idle: true, ..cfg(3) }; + let cfg = DigestConfig { + endpoint_idle: true, + ..cfg(3) + }; assert!( project_timeline(&[], &cfg).turns.is_empty(), "an idle endpoint with no records has no turn to seal" @@ -1222,7 +1314,10 @@ mod tests { // turn, not of a window position, and the surviving turns keep their seqs. #[test] fn sealing_survives_a_window_slide() { - let cfg = DigestConfig { endpoint_idle: true, ..cfg(2) }; + let cfg = DigestConfig { + endpoint_idle: true, + ..cfg(2) + }; let mut items = vec![ act_seq(DigestRole::Input, "t0", 100), act_seq(DigestRole::Agent, "r0", 101), @@ -1235,11 +1330,27 @@ mod tests { items.push(act_seq(DigestRole::Input, "t2", 300)); items.push(act_seq(DigestRole::Agent, "r2", 301)); let after = project_timeline(&items, &cfg); - let inputs: Vec<_> = after.turns.iter().filter_map(|t| t.input.as_deref()).collect(); - assert_eq!(inputs, vec!["t1", "t2"], "PRECONDITION: the window slid, t0 dropped"); - assert_eq!(trailing_seqs(&after), (Some(300), Some(301)), "the NEW trailing turn seals"); + let inputs: Vec<_> = after + .turns + .iter() + .filter_map(|t| t.input.as_deref()) + .collect(); + assert_eq!( + inputs, + vec!["t1", "t2"], + "PRECONDITION: the window slid, t0 dropped" + ); + assert_eq!( + trailing_seqs(&after), + (Some(300), Some(301)), + "the NEW trailing turn seals" + ); // t1 slid from trailing to committed and kept the seq it was sealed with. - assert_eq!(after.turns[0].input_seq, Some(200), "a sealed seq survives the slide"); + assert_eq!( + after.turns[0].input_seq, + Some(200), + "a sealed seq survives the slide" + ); assert!(!after.turns[0].partial); } @@ -1257,13 +1368,20 @@ mod tests { // value skip the appended tool entirely (it would EAT stragglers). #[test] fn a_sealed_sprint_grows_forward_only_keeping_the_turn_anchor_stable() { - let cfg = DigestConfig { endpoint_idle: true, ..cfg(3) }; + let cfg = DigestConfig { + endpoint_idle: true, + ..cfg(3) + }; let base = vec![ act_seq(DigestRole::Input, "run the build", 10), tool_seq("Bash", 11), ]; let before = project_timeline(&base, &cfg); - assert_eq!(trailing_seqs(&before), (Some(10), Some(11)), "PRECONDITION: sealed at 10/11"); + assert_eq!( + trailing_seqs(&before), + (Some(10), Some(11)), + "PRECONDITION: sealed at 10/11" + ); let mut late = base.clone(); late.push(tool_seq("Read", 12)); // a straggler TOOL, adjacent to the sprint @@ -1280,8 +1398,10 @@ mod tests { // (2) Forward only. let (_, before_sprint) = trailing_seqs(&before); let (_, after_sprint) = trailing_seqs(&after); - let (before_sprint, after_sprint) = - (before_sprint.expect("sealed sprint seq"), after_sprint.expect("grown sprint seq")); + let (before_sprint, after_sprint) = ( + before_sprint.expect("sealed sprint seq"), + after_sprint.expect("grown sprint seq"), + ); assert!( after_sprint > before_sprint, "an entry seq may only advance FORWARD on sprint growth ({before_sprint} -> \ @@ -1311,6 +1431,9 @@ mod tests { _ => None, }) .expect("a sprint"); - assert_eq!(tools, 2, "and the re-delivered sprint carries BOTH tools, so nothing is lost"); + assert_eq!( + tools, 2, + "and the re-delivered sprint carries BOTH tools, so nothing is lost" + ); } } diff --git a/crates/spt-term/src/reader.rs b/crates/spt-term/src/reader.rs index 822cae13..591e8124 100644 --- a/crates/spt-term/src/reader.rs +++ b/crates/spt-term/src/reader.rs @@ -313,7 +313,10 @@ mod tests { // Split `\x1b[6n` across two feeds: one answer, query stripped. let (fwd, answers) = split_all(&[b"output\x1b[", b"6nmore"]); assert_eq!(answers, 1); - assert_eq!(fwd, b"outputmore", "the query is stripped, everything else forwards"); + assert_eq!( + fwd, b"outputmore", + "the query is stripped, everything else forwards" + ); // A lone ESC that restarts a match mid-stream, then completes — the // withheld non-query ESC still forwards. let (fwd, answers) = split_all(&[b"\x1b\x1b[6n"]); diff --git a/crates/spt-term/src/screen.rs b/crates/spt-term/src/screen.rs index 33cdb9c0..699b328d 100644 --- a/crates/spt-term/src/screen.rs +++ b/crates/spt-term/src/screen.rs @@ -555,7 +555,11 @@ impl GridState { self.buf_mut()[row][col] = Cell { ch: c, marks: Vec::new(), - kind: if wide { CellKind::WideLead } else { CellKind::Narrow }, + kind: if wide { + CellKind::WideLead + } else { + CellKind::Narrow + }, pen, }; if wide { @@ -1272,7 +1276,7 @@ impl Perform for GridState { return; } match byte { - b'c' => self.full_reset(), // RIS + b'c' => self.full_reset(), // RIS b'7' => self.saved = Some((self.row, self.col)), // DECSC b'8' => { // DECRC @@ -1340,10 +1344,16 @@ mod tests { let out = repaint(&[b"\x1b[5;10r"], 24, 80); let stbm = out.find("\x1b[5;10r").expect("tracked DECSTBM replayed"); let cursor = out.rfind("H").expect("final cursor placement"); - assert!(stbm < cursor, "DECSTBM precedes the final cursor placement:\n{out:?}"); + assert!( + stbm < cursor, + "DECSTBM precedes the final cursor placement:\n{out:?}" + ); // Default region → explicit reset, never an omitted mode. let out = repaint(&[b"plain"], 24, 80); - assert!(out.contains("\x1b[r"), "default region resets explicitly:\n{out:?}"); + assert!( + out.contains("\x1b[r"), + "default region resets explicitly:\n{out:?}" + ); assert!(!out.contains(";24r"), "no spurious tracked-region emit"); } @@ -1381,11 +1391,20 @@ mod tests { #[test] fn main_screen_repaint_paints_text_no_alt_enter() { let out = repaint(&[b"hello world"], 24, 80); - assert!(out.contains("hello world"), "repaint paints the text: {out:?}"); + assert!( + out.contains("hello world"), + "repaint paints the text: {out:?}" + ); assert!(out.contains("\x1b[?1049l"), "client stays on main buffer"); - assert!(!out.contains("\x1b[?1049h"), "no alt-screen enter for a main screen"); + assert!( + !out.contains("\x1b[?1049h"), + "no alt-screen enter for a main screen" + ); // Cursor ends after the 11 printed columns (col 12, 1-based). - assert!(out.contains("\x1b[1;12H"), "cursor at live position: {out:?}"); + assert!( + out.contains("\x1b[1;12H"), + "cursor at live position: {out:?}" + ); } // The #6 CORE: after entering the alt screen, the repaint paints ONLY the @@ -1396,15 +1415,21 @@ mod tests { fn alt_screen_repaint_excludes_main_scrollback() { let out = repaint( &[ - b"MAIN-SCROLLBACK-LINE\r\n", // main screen history - b"\x1b[?1049h", // enter alt screen - b"\x1b[2J\x1b[HTUI-VIEWPORT", // paint the TUI + b"MAIN-SCROLLBACK-LINE\r\n", // main screen history + b"\x1b[?1049h", // enter alt screen + b"\x1b[2J\x1b[HTUI-VIEWPORT", // paint the TUI ], 24, 80, ); - assert!(out.contains("\x1b[?1049h"), "repaint puts the client in the alt screen"); - assert!(out.contains("TUI-VIEWPORT"), "alt content is painted: {out:?}"); + assert!( + out.contains("\x1b[?1049h"), + "repaint puts the client in the alt screen" + ); + assert!( + out.contains("TUI-VIEWPORT"), + "alt content is painted: {out:?}" + ); assert!( !out.contains("MAIN-SCROLLBACK-LINE"), "main scrollback must NOT appear in an alt repaint (the #6 corruption): {out:?}" @@ -1426,8 +1451,14 @@ mod tests { 80, ); assert!(out.contains("\x1b[?1049l"), "client returned to main"); - assert!(out.contains("back-on-main"), "main content restored: {out:?}"); - assert!(!out.contains("alt-only"), "alt content gone after leaving: {out:?}"); + assert!( + out.contains("back-on-main"), + "main content restored: {out:?}" + ); + assert!( + !out.contains("alt-only"), + "alt content gone after leaving: {out:?}" + ); } // SGR pen state is reconstructed in the repaint (colour + bold), and the reset @@ -1437,7 +1468,10 @@ mod tests { fn sgr_pen_reconstructed_in_repaint() { let out = repaint(&[b"\x1b[1;31mRED\x1b[0m plain"], 24, 80); assert!(out.contains("RED"), "text painted"); - assert!(out.contains("\x1b[0;1;31m"), "bold-red SGR reconstructed: {out:?}"); + assert!( + out.contains("\x1b[0;1;31m"), + "bold-red SGR reconstructed: {out:?}" + ); assert!(out.contains("plain"), "trailing plain text painted"); } @@ -1475,7 +1509,10 @@ mod tests { let out = repaint(&[b"\x1b]2;doomed\x07", b"\x1bc"], 24, 80); assert!(!out.contains("\x1b]2;"), "RIS cleared the title: {out:?}"); let out = repaint(&[b"plain"], 24, 80); - assert!(!out.contains("\x1b]2;"), "no title ever set → none replayed"); + assert!( + !out.contains("\x1b]2;"), + "no title ever set → none replayed" + ); } // E-2: a resize does not drop the title (only buffers reflow). @@ -1486,7 +1523,10 @@ mod tests { g.advance(b"\x1b]2;sticky\x07"); g.resize(10, 40); let out = String::from_utf8(g.render_repaint()).unwrap(); - assert!(out.contains("\x1b]2;sticky\x07"), "title survives resize: {out:?}"); + assert!( + out.contains("\x1b]2;sticky\x07"), + "title survives resize: {out:?}" + ); } // A resize preserves the visible top-left content. @@ -1515,7 +1555,10 @@ mod tests { #[test] fn cursor_visibility_hidden_emitted() { let out = repaint(&[b"\x1b[?25l"], 24, 80); - assert!(out.contains("\x1b[?25l"), "hidden cursor reflected: {out:?}"); + assert!( + out.contains("\x1b[?25l"), + "hidden cursor reflected: {out:?}" + ); } // An empty grid (nothing produced) repaints to a clean clear with no cell rows. @@ -1537,7 +1580,10 @@ mod tests { #[test] fn wide_glyph_advances_two_display_columns() { let out = repaint(&["世A".as_bytes()], 24, 80); - assert!(out.contains("世A"), "lead emitted once, no continuation debris: {out:?}"); + assert!( + out.contains("世A"), + "lead emitted once, no continuation debris: {out:?}" + ); assert!( out.contains("\x1b[1;4H"), "cursor at display col 4 after a wide glyph + narrow (not scalar col 3): {out:?}" @@ -1551,7 +1597,11 @@ mod tests { fn cursor_position_reports_display_columns() { let mut g = ScreenGrid::new(24, 80); g.advance("世".as_bytes()); - assert_eq!(g.cursor_position(), (1, 3), "wide glyph consumes 2 display columns"); + assert_eq!( + g.cursor_position(), + (1, 3), + "wide glyph consumes 2 display columns" + ); g.advance(b"X"); assert_eq!(g.cursor_position(), (1, 4)); } @@ -1564,8 +1614,14 @@ mod tests { // 3-col grid: `AB` fills cols 1-2, `世` needs 2 cols but only col 3 // remains → whole glyph wraps to row 2. let out = repaint(&["AB世".as_bytes()], 4, 3); - assert!(out.contains("\x1b[1;1HAB"), "row 1 keeps the narrow prefix: {out:?}"); - assert!(out.contains("\x1b[2;1H世"), "the wide glyph wrapped WHOLE to row 2: {out:?}"); + assert!( + out.contains("\x1b[1;1HAB"), + "row 1 keeps the narrow prefix: {out:?}" + ); + assert!( + out.contains("\x1b[2;1H世"), + "the wide glyph wrapped WHOLE to row 2: {out:?}" + ); } // Overwriting EITHER half of a wide glyph clears the whole glyph — no @@ -1576,13 +1632,22 @@ mod tests { fn overwriting_either_half_clears_the_whole_wide_glyph() { // Overwrite the CONTINUATION (col 2): the lead must die with it. let out = repaint(&["世".as_bytes(), b"\x1b[1;2HX"], 24, 80); - assert!(!out.contains('世'), "lead cleared when its continuation is overwritten: {out:?}"); + assert!( + !out.contains('世'), + "lead cleared when its continuation is overwritten: {out:?}" + ); assert!(out.contains('X'), "the overwriting char landed: {out:?}"); // Overwrite the LEAD (col 1): the continuation must die with it. let out = repaint(&["世Z".as_bytes(), b"\x1b[1;1HY"], 24, 80); - assert!(!out.contains('世'), "glyph cleared when its lead is overwritten: {out:?}"); + assert!( + !out.contains('世'), + "glyph cleared when its lead is overwritten: {out:?}" + ); // Y at col 1, old continuation at col 2 is now a blank, Z still at col 3. - assert!(out.contains("\x1b[1;1HY Z"), "continuation became a real blank: {out:?}"); + assert!( + out.contains("\x1b[1;1HY Z"), + "continuation became a real blank: {out:?}" + ); } // ECH/EL landing on one half of a wide pair heals both halves. @@ -1591,11 +1656,17 @@ mod tests { fn erase_across_a_wide_half_leaves_no_orphan() { // ECH 1 on the lead: continuation must not survive as phantom content. let out = repaint(&["世".as_bytes(), b"\x1b[1;1H\x1b[1X"], 24, 80); - assert!(!out.contains('世'), "ECH on the lead clears the pair: {out:?}"); + assert!( + !out.contains('世'), + "ECH on the lead clears the pair: {out:?}" + ); // EL from the continuation column: the lead (left of the erase range) // must not survive as a half-glyph. let out = repaint(&["世AB".as_bytes(), b"\x1b[1;2H\x1b[0K"], 24, 80); - assert!(!out.contains('世'), "EL starting on the continuation clears the lead too: {out:?}"); + assert!( + !out.contains('世'), + "EL starting on the continuation clears the lead too: {out:?}" + ); } // ICH/DCH shift in display cells and never leave a mispaired half. The @@ -1606,12 +1677,21 @@ mod tests { fn dch_ich_heal_wide_pairs_at_the_boundaries() { let out = repaint(&["世界".as_bytes(), b"\x1b[1;1H\x1b[1P"], 24, 80); assert!(!out.contains('世'), "deleted wide glyph is gone: {out:?}"); - assert!(out.contains('界'), "the following wide glyph shifted intact: {out:?}"); + assert!( + out.contains('界'), + "the following wide glyph shifted intact: {out:?}" + ); // ICH at the continuation column of 世: the pair heals, then blanks // are inserted — 界 must survive intact further right. let out = repaint(&["世界".as_bytes(), b"\x1b[1;2H\x1b[2@"], 24, 80); - assert!(!out.contains('世'), "ICH on a continuation heals the pair: {out:?}"); - assert!(out.contains('界'), "the neighbouring glyph shifted whole: {out:?}"); + assert!( + !out.contains('世'), + "ICH on a continuation heals the pair: {out:?}" + ); + assert!( + out.contains('界'), + "the neighbouring glyph shifted whole: {out:?}" + ); } // Width-0 combining marks attach to the preceding grapheme without @@ -1620,7 +1700,10 @@ mod tests { #[test] fn combining_mark_attaches_without_advancing() { let out = repaint(&["e\u{0301}Z".as_bytes()], 24, 80); - assert!(out.contains("e\u{0301}Z"), "mark rides its base in the repaint: {out:?}"); + assert!( + out.contains("e\u{0301}Z"), + "mark rides its base in the repaint: {out:?}" + ); assert!( out.contains("\x1b[1;3H"), "cursor advanced 2 columns for 3 scalars (the mark is width-0): {out:?}" @@ -1632,7 +1715,10 @@ mod tests { g.advance("\u{0301}".as_bytes()); assert_eq!(g.cursor_position(), (1, 3), "width-0 mark did not advance"); let out = String::from_utf8(g.render_repaint()).unwrap(); - assert!(out.contains("世\u{0301}"), "mark attached to the wide lead: {out:?}"); + assert!( + out.contains("世\u{0301}"), + "mark attached to the wide lead: {out:?}" + ); } // A resize that truncates THROUGH a wide pair heals the cut lead — a @@ -1644,8 +1730,14 @@ mod tests { g.advance("AB世".as_bytes()); // AB at cols 1-2, 世 at cols 3-4 g.resize(4, 3); // cut at col 4: 世's continuation is gone let out = String::from_utf8(g.render_repaint()).unwrap(); - assert!(!out.contains('世'), "the cut lead healed to a blank: {out:?}"); - assert!(out.contains("AB"), "untouched content survives the resize: {out:?}"); + assert!( + !out.contains('世'), + "the cut lead healed to a blank: {out:?}" + ); + assert!( + out.contains("AB"), + "untouched content survives the resize: {out:?}" + ); } // ── REQ-RC-RESIZE-PRESENTATION-BARRIER leg 5: capture-mode disposition ── @@ -1682,7 +1774,10 @@ mod tests { } // The grid still consumed the printable text at full fidelity. let out = String::from_utf8(g.render_repaint()).unwrap(); - assert!(out.contains("hello world"), "text advanced the grid: {out:?}"); + assert!( + out.contains("hello world"), + "text advanced the grid: {out:?}" + ); } // TRACKED state (title, cursor visibility, DECSTBM, alt screen, pen, cursor) @@ -1701,7 +1796,10 @@ mod tests { ); let out = String::from_utf8(g.render_repaint()).unwrap(); assert!(out.contains("\x1b]2;t\x07"), "title tracked: {out:?}"); - assert!(out.contains("\x1b[?25l"), "cursor visibility tracked: {out:?}"); + assert!( + out.contains("\x1b[?25l"), + "cursor visibility tracked: {out:?}" + ); assert!(out.contains("\x1b[?1049h"), "alt screen tracked: {out:?}"); } @@ -1735,7 +1833,10 @@ mod tests { let mut g = ScreenGrid::new(6, 40); let cap = g.advance_captured(b"\x1b]10;?\x07\x1b]11;rgb:1a/2b/3c\x1b\\"); let cap = String::from_utf8(cap).unwrap(); - assert!(cap.contains("\x1b]10;?\x07"), "BEL-terminated query kept BEL: {cap:?}"); + assert!( + cap.contains("\x1b]10;?\x07"), + "BEL-terminated query kept BEL: {cap:?}" + ); assert!( cap.contains("\x1b]11;rgb:1a/2b/3c\x1b\\"), "ST-terminated set kept ST: {cap:?}" @@ -1768,8 +1869,14 @@ mod tests { let mut g = ScreenGrid::new(6, 40); let cap = g.advance_captured(b"\x1b[?2004h\x1bc\x1b[?1000h"); let cap = String::from_utf8(cap).unwrap(); - assert!(cap.contains("\x1b[?2004h"), "pre-RIS deferred bytes survive: {cap:?}"); - assert!(cap.contains("\x1b[?1000h"), "post-RIS bytes keep deferring: {cap:?}"); + assert!( + cap.contains("\x1b[?2004h"), + "pre-RIS deferred bytes survive: {cap:?}" + ); + assert!( + cap.contains("\x1b[?1000h"), + "post-RIS bytes keep deferring: {cap:?}" + ); } // The LIVE path is untouched: plain `advance` defers nothing and ignores @@ -1783,7 +1890,10 @@ mod tests { assert!(cap.is_empty(), "nothing latent leaks into a later capture"); let out = String::from_utf8(g.render_repaint()).unwrap(); assert!(out.contains("plain")); - assert!(!out.contains("\x1b[?2004h"), "untracked mode is not in the repaint"); + assert!( + !out.contains("\x1b[?2004h"), + "untracked mode is not in the repaint" + ); } // The field-repro shape (hertz RCA): wide glyphs + row-addressed redraw. diff --git a/crates/spt-term/src/winprog.rs b/crates/spt-term/src/winprog.rs index 31996899..6d6e9cc2 100644 --- a/crates/spt-term/src/winprog.rs +++ b/crates/spt-term/src/winprog.rs @@ -283,7 +283,10 @@ mod tests { fn unresolvable_passes_through() { let dirs = vec![PathBuf::from("C:/tools")]; let none = exists_set(&[]); - assert_eq!(resolve_in("nope", &dirs, &exts(), none), Launch::Passthrough); + assert_eq!( + resolve_in("nope", &dirs, &exts(), none), + Launch::Passthrough + ); } // First PATH dir with a match wins (search order honoured). diff --git a/crates/spt-term/tests/capture_vehicle_fidelity.rs b/crates/spt-term/tests/capture_vehicle_fidelity.rs index e985874b..2b3809b4 100644 --- a/crates/spt-term/tests/capture_vehicle_fidelity.rs +++ b/crates/spt-term/tests/capture_vehicle_fidelity.rs @@ -51,7 +51,10 @@ const COLS: u16 = 131; fn fixture() -> std::path::PathBuf { let p = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) .join("../spt-daemon/tests/fixtures/enlyzeam/tap-1-raw.log"); - assert!(p.exists(), "the ENLYZEAM capture must be committed at {p:?}"); + assert!( + p.exists(), + "the ENLYZEAM capture must be committed at {p:?}" + ); p } @@ -134,7 +137,10 @@ fn through_vehicle(mode: &str) -> Vec { std::thread::sleep(std::time::Duration::from_secs(5)); let got = acc.lock().expect("lock").clone(); let _ = pty.kill(); - assert!(!got.is_empty(), "precondition: the vehicle emitted something"); + assert!( + !got.is_empty(), + "precondition: the vehicle emitted something" + ); got } diff --git a/crates/spt-term/tests/rc_console_newline_presentation.rs b/crates/spt-term/tests/rc_console_newline_presentation.rs index 6cf1b53d..6f3e8234 100644 --- a/crates/spt-term/tests/rc_console_newline_presentation.rs +++ b/crates/spt-term/tests/rc_console_newline_presentation.rs @@ -102,7 +102,10 @@ fn through_console(mode: &str) -> Vec { std::thread::sleep(std::time::Duration::from_secs(3)); let got = acc.lock().expect("lock").clone(); let _ = pty.kill(); - assert!(!got.is_empty(), "precondition: the player emitted something"); + assert!( + !got.is_empty(), + "precondition: the player emitted something" + ); got } diff --git a/crates/spt-term/tests/resize_console_mode_integrity.rs b/crates/spt-term/tests/resize_console_mode_integrity.rs index 485da43c..b0b46954 100644 --- a/crates/spt-term/tests/resize_console_mode_integrity.rs +++ b/crates/spt-term/tests/resize_console_mode_integrity.rs @@ -297,7 +297,9 @@ fn the_rig_detects_a_seeded_console_input_mode_change() { // ...and the SYMPTOM leg's observable must move too, or that leg is passing // for reasons unrelated to echo. Typed bytes must now come back as output. let before = rig.text(); - rig.pty.write_input(b"zqxjv\r").expect("type into the child"); + rig.pty + .write_input(b"zqxjv\r") + .expect("type into the child"); let deadline = Instant::now() + Duration::from_secs(5); let mut echoed = false; while Instant::now() < deadline && !echoed { @@ -350,5 +352,8 @@ fn the_probe_report_parses_out_of_a_re_rendered_stream() { // Not a report at all — must not be mistaken for one. assert!(parse("\u{1b}[8;60;131t").is_none()); - assert!(parse("MODE tag=broken in=0x1").is_none(), "a partial report is refused"); + assert!( + parse("MODE tag=broken in=0x1").is_none(), + "a partial report is refused" + ); } diff --git a/crates/spt-term/tests/screengrid_width_oracle.rs b/crates/spt-term/tests/screengrid_width_oracle.rs index fa906175..0ab1729f 100644 --- a/crates/spt-term/tests/screengrid_width_oracle.rs +++ b/crates/spt-term/tests/screengrid_width_oracle.rs @@ -81,7 +81,10 @@ fn cup_overwrite_after_wide_glyphs_lands_on_the_same_cells() { let raw = "世界Today\x1b[1;5HNEW"; assert_matches_authority(raw, 2, 20, "CUP overwrite after wide glyphs"); let auth = authoritative(raw, 2, 20); - assert_eq!(auth[0], "世界NEWay", "NEW lands at display cols 5-7 over Today"); + assert_eq!( + auth[0], "世界NEWay", + "NEW lands at display cols 5-7 over Today" + ); } // Case 3: a zero-width combining mark survives the synthesized repaint diff --git a/crates/spt-term/tests/winspawn.rs b/crates/spt-term/tests/winspawn.rs index 72525b0b..e513ca2b 100644 --- a/crates/spt-term/tests/winspawn.rs +++ b/crates/spt-term/tests/winspawn.rs @@ -41,8 +41,8 @@ fn pty_spawns_a_cmd_script_via_cmd_wrap() { pid.is_some(), "the cmd.exe wrapper child has a real pid (it actually launched)" ), - Err(e) => panic!( - "a .cmd must spawn under a PTY via the cmd.exe wrap, never os error 193: {e}" - ), + Err(e) => { + panic!("a .cmd must spawn under a PTY via the cmd.exe wrap, never os error 193: {e}") + } } } diff --git a/crates/spt/src/accessview.rs b/crates/spt/src/accessview.rs index 2eb92012..37509d1d 100644 --- a/crates/spt/src/accessview.rs +++ b/crates/spt/src/accessview.rs @@ -142,9 +142,10 @@ pub fn roster_for_target( .iter() .find(|(n, _)| n == &name) .and_then(|(_, m)| mode_word(m)); - let rules = count_where(&acl.rules, |s| { - matches!(s, Subject::SubnetWildcard { subnet } if subnet == &name) - }); + let rules = count_where( + &acl.rules, + |s| matches!(s, Subject::SubnetWildcard { subnet } if subnet == &name), + ); items.push(RosterItem::Subnet { subnet: name, mode, @@ -168,9 +169,10 @@ pub fn roster_for_target( } } for node in nodes { - let rules = count_where(&acl.rules, |s| { - matches!(s, Subject::Node { node: n } if n == &node) - }); + let rules = count_where( + &acl.rules, + |s| matches!(s, Subject::Node { node: n } if n == &node), + ); items.push(RosterItem::ExternalNode { node, rules }); } // Sender endpoints the target's rules name. @@ -183,9 +185,10 @@ pub fn roster_for_target( } } for id in eps { - let rules = count_where(&acl.rules, |s| { - matches!(s, Subject::SenderEndpoint { id: i } if i == &id) - }); + let rules = count_where( + &acl.rules, + |s| matches!(s, Subject::SenderEndpoint { id: i } if i == &id), + ); let (node, shared) = dir .get(&id) .map(|(n, s)| (Some(n.clone()), s.clone())) @@ -230,9 +233,10 @@ pub fn roster_for_node( .iter() .find(|(n, _)| n == &name) .and_then(|(_, m)| mode_word(m)); - let rules = count_where(&node.rules, |s| { - matches!(s, Subject::SubnetWildcard { subnet } if subnet == &name) - }); + let rules = count_where( + &node.rules, + |s| matches!(s, Subject::SubnetWildcard { subnet } if subnet == &name), + ); items.push(RosterItem::Subnet { subnet: name, mode, @@ -254,9 +258,10 @@ pub fn roster_for_node( } } for n in nodes { - let rules = count_where(&node.rules, |s| { - matches!(s, Subject::Node { node: x } if x == &n) - }); + let rules = count_where( + &node.rules, + |s| matches!(s, Subject::Node { node: x } if x == &n), + ); items.push(RosterItem::ExternalNode { node: n, rules }); } items @@ -300,9 +305,7 @@ fn render_item(item: &RosterItem, color: bool) -> String { } line } - RosterItem::HomeNode { node, mode } => { - wrap(&format!("{node} - mode: {mode}"), CYAN, color) - } + RosterItem::HomeNode { node, mode } => wrap(&format!("{node} - mode: {mode}"), CYAN, color), RosterItem::ExternalNode { node, rules } => { wrap(&format!("{node} - {}", count(*rules)), DIM_GRAY, color) } @@ -396,9 +399,15 @@ mod tests { endpoint: "wanda".into(), rules: vec![ rule(Subject::SenderEndpoint { id: "flynn".into() }), - rule(Subject::Node { node: "ffff".into() }), - rule(Subject::SubnetWildcard { subnet: "bignet".into() }), - rule(Subject::SubnetWildcard { subnet: "bignet".into() }), + rule(Subject::Node { + node: "ffff".into(), + }), + rule(Subject::SubnetWildcard { + subnet: "bignet".into(), + }), + rule(Subject::SubnetWildcard { + subnet: "bignet".into(), + }), rule(Subject::SenderEndpoint { id: "ghost".into() }), ], modes: Modes::default(), @@ -412,13 +421,7 @@ mod tests { "flynn".into(), ("kitsubito".into(), vec!["bignet".into(), "quietnet".into()]), ); - let items = roster_for_target( - &acl, - &modes_all(Mode::Open), - &captured, - "HFENDULEAM", - &dir, - ); + let items = roster_for_target(&acl, &modes_all(Mode::Open), &captured, "HFENDULEAM", &dir); assert_eq!( items, vec![ @@ -479,7 +482,9 @@ mod tests { let mut modes = modes_all(Mode::Closed); modes.per_surface.insert("MSG".into(), Mode::Open); let node = NodeAcl { - rules: vec![rule(Subject::Node { node: "aaaa".into() })], + rules: vec![rule(Subject::Node { + node: "aaaa".into(), + })], modes, }; let items = roster_for_node(&node, &[], "HFENDULEAM"); diff --git a/crates/spt/src/api/auth.rs b/crates/spt/src/api/auth.rs index f94a941f..23dde02a 100644 --- a/crates/spt/src/api/auth.rs +++ b/crates/spt/src/api/auth.rs @@ -497,7 +497,11 @@ mod tests { let token = establish_with_pid("alice", "old-dead-sid", DEAD_PID); // Correct token PLUS a mismatched sid: the token path wins first. let proof = Proof::resolve(Some(token), Some("new-live-sid".into())); - assert_eq!(authenticate("alice", &proof), AuthResult::Ok, "token authenticates"); + assert_eq!( + authenticate("alice", &proof), + AuthResult::Ok, + "token authenticates" + ); assert_eq!( recorded_sid("alice"), "old-dead-sid", @@ -514,7 +518,13 @@ mod tests { std::fs::create_dir_all(&path).unwrap(); info::write_info( &path, - &InfoJson::new(&psyche_id, "2026-06-01T00:00:00Z", std::process::id(), session, "psyche"), + &InfoJson::new( + &psyche_id, + "2026-06-01T00:00:00Z", + std::process::id(), + session, + "psyche", + ), ) .unwrap(); } @@ -522,7 +532,12 @@ mod tests { /// Establish a top-level parent perch pinned to `sid`, plus a nested worker /// `owlery//nested/` whose STORED registration sid is /// `stored_sid` — the WORKER-TRUTH W-2 layout the sid-symmetric auth reads. - fn establish_parent_with_worker(parent: &str, parent_sid: &str, worker: &str, stored_sid: &str) { + fn establish_parent_with_worker( + parent: &str, + parent_sid: &str, + worker: &str, + stored_sid: &str, + ) { let ppath = perch::resolve_perch_path(parent, ParentHint::Infer); std::fs::create_dir_all(&ppath).unwrap(); info::write_info( @@ -596,7 +611,10 @@ mod tests { fn worker_missing_is_no_endpoint() { let _h = isolated_home(); let proof = Proof::resolve(None, Some("sid-1".into())); - assert_eq!(worker_authenticate("ghost-w1", &proof), AuthResult::NoEndpoint); + assert_eq!( + worker_authenticate("ghost-w1", &proof), + AuthResult::NoEndpoint + ); } // [unit->REQ-BIND-HONEST-SELF-STAMP] CROSS-PERCH BIND HONESTY: the dead-owner diff --git a/crates/spt/src/api/delivery.rs b/crates/spt/src/api/delivery.rs index a63210b3..d4f4b53d 100644 --- a/crates/spt/src/api/delivery.rs +++ b/crates/spt/src/api/delivery.rs @@ -371,7 +371,9 @@ fn launch_detached_mint(id: &str, text: &str) { let exe = match std::env::current_exe() { Ok(p) => p, Err(e) => { - spt_proto::emit_line_err!("SEAL_SHORTFORM_WARN:{id}: cannot locate the spt binary ({e})"); + spt_proto::emit_line_err!( + "SEAL_SHORTFORM_WARN:{id}: cannot locate the spt binary ({e})" + ); return; } }; @@ -397,7 +399,9 @@ fn launch_detached_mint(id: &str, text: &str) { // Deliberately NOT waited on: the hook returns now, the ceremony // runs on, and the child records its own outcome. } - Err(e) => spt_proto::emit_line_err!("SEAL_SHORTFORM_WARN:{id}: could not start the mint ({e})"), + Err(e) => { + spt_proto::emit_line_err!("SEAL_SHORTFORM_WARN:{id}: could not start the mint ({e})") + } } } @@ -727,8 +731,8 @@ pub fn poll_drain(id: &str, include_deferred: bool) -> Vec { // [impl->REQ-MSG-DELIVERY-AXES] // [impl->REQ-SPOOL-TAKE-AUDIT] hook-poll leg — record who drained the row. let audit = spool::TakerAudit::new(spool::TakerLeg::HookPoll, None, Some(std::process::id())); - let drained = - spool::drain_active_window_audited_at(&perch_path, include_deferred, &audit).unwrap_or_default(); + let drained = spool::drain_active_window_audited_at(&perch_path, include_deferred, &audit) + .unwrap_or_default(); // DRAIN-TIME NOTIF VALIDITY (ADR-0046 Amendment 1, KNOWN-HAZARDS 7.53): a // notify copy spooled while the endpoint was busy is a detached snapshot no // dismissal can recall — it delivers "update available" on a node that has @@ -866,8 +870,14 @@ mod tests { // constant for everything. #[test] fn payload_carrying_calls_map_to_their_kinds() { - assert_eq!(super::state_io_kind("busy", true, false), Some("USER_INPUT")); - assert_eq!(super::state_io_kind("idle", true, false), Some("AGENT_OUTPUT")); + assert_eq!( + super::state_io_kind("busy", true, false), + Some("USER_INPUT") + ); + assert_eq!( + super::state_io_kind("idle", true, false), + Some("AGENT_OUTPUT") + ); } // [unit->REQ-IO-INGEST-STATE-PAYLOAD] no payload ⇒ no event, for BOTH @@ -910,12 +920,18 @@ mod tests { let _h = isolated_home(); let id = "iofunnel-edge"; establish(id); - assert_eq!(super::cmd_state(id, "idle", true, Some("first"), false, false), 0); + assert_eq!( + super::cmd_state(id, "idle", true, Some("first"), false, false), + 0 + ); let perch_path = perch::resolve_perch_path(id, ParentHint::Infer); let first = perch::read_activity_at(&perch_path).1; assert!(first.is_some(), "the first report dates the state"); std::thread::sleep(std::time::Duration::from_millis(5)); - assert_eq!(super::cmd_state(id, "idle", true, Some("second"), false, false), 0); + assert_eq!( + super::cmd_state(id, "idle", true, Some("second"), false, false), + 0 + ); let second = perch::read_activity_at(&perch_path).1; assert_eq!( first, second, @@ -1024,7 +1040,11 @@ mod tests { super::dispatch_seal_mints_via(";;first;; middle ;;second;;", false, &mut |t| { seen.push(t.to_string()) }); - assert_eq!(seen, vec!["first", "second"], "two pairs, two launches: {seen:?}"); + assert_eq!( + seen, + vec!["first", "second"], + "two pairs, two launches: {seen:?}" + ); } // [unit->REQ-IO-SEAL-SHORTFORM-CEREMONY] a payload with no live marker @@ -1036,7 +1056,10 @@ mod tests { super::dispatch_seal_mints_via("ordinary turn output", false, &mut |_| count += 1); super::dispatch_seal_mints_via("quoted `;;nope;;` only", false, &mut |_| count += 1); super::dispatch_seal_mints_via(";;;;", false, &mut |_| count += 1); - assert_eq!(count, 0, "no marker, a quoted marker, and an empty pair all launch nothing"); + assert_eq!( + count, 0, + "no marker, a quoted marker, and an empty pair all launch nothing" + ); } // [unit->REQ-IO-MIDTURN-SPAN] THE WHOLE KIND TABLE, INCLUDING THE ARM THIS @@ -1053,8 +1076,14 @@ mod tests { Some("AGENT_OUTPUT"), "a mid-turn span is agent output, not user input" ); - assert_eq!(super::state_io_kind("busy", true, false), Some("USER_INPUT")); - assert_eq!(super::state_io_kind("idle", true, false), Some("AGENT_OUTPUT")); + assert_eq!( + super::state_io_kind("busy", true, false), + Some("USER_INPUT") + ); + assert_eq!( + super::state_io_kind("idle", true, false), + Some("AGENT_OUTPUT") + ); // The back-compat arm is indifferent to the new flag: no payload, no // event, whatever else was passed. assert_eq!(super::state_io_kind("busy", false, true), None); @@ -1102,8 +1131,9 @@ mod tests { ); let mut close_launched: Vec = Vec::new(); - let refused_at_close = - super::dispatch_seal_mints_via(text, false, &mut |t| close_launched.push(t.to_string())); + let refused_at_close = super::dispatch_seal_mints_via(text, false, &mut |t| { + close_launched.push(t.to_string()) + }); assert_eq!(refused_at_close, 0); assert_eq!( close_launched, @@ -1119,9 +1149,10 @@ mod tests { #[test] fn a_pair_still_mints_mid_turn_and_a_trailing_marker_does_not() { let mut launched: Vec = Vec::new(); - let refused = super::dispatch_seal_mints_via(";;sealed;; then ;;dangling", true, &mut |t| { - launched.push(t.to_string()) - }); + let refused = + super::dispatch_seal_mints_via(";;sealed;; then ;;dangling", true, &mut |t| { + launched.push(t.to_string()) + }); assert_eq!(launched, vec!["sealed"], "the pair minted mid-turn"); assert_eq!(refused, 1, "the odd trailing marker did not"); } @@ -1154,13 +1185,20 @@ mod tests { // doyle. Without this the arms below would pass on a typo'd string that // was never a tag in the first place. let parsed = spt_proto::shortform::parse_tags(hostile); - assert_eq!(parsed.len(), 1, "the fixture must BE a live tag: {parsed:?}"); + assert_eq!( + parsed.len(), + 1, + "the fixture must BE a live tag: {parsed:?}" + ); assert_eq!(parsed[0].targets, vec!["doyle"]); spool::spool_message_at(&alice, "bob", hostile).unwrap(); let got = poll_drain("alice", false); assert_eq!(got.len(), 1, "it still DELIVERS as ordinary text: {got:?}"); - assert!(got[0].body.contains("@REQ-SEAM-ACTIVITY] idle writes .idle + arms the gate; busy clears .idle. - // [unit->REQ-ECHO-IDLE-AGE-GATE] and it arms the WORK arm, never the edge one. + // [unit->REQ-ECHO-IDLE-AGE-GATE] and it arms the WORK arm, never the edge one. fn idle_busy_transitions_manage_sentinels() { let _h = isolated_home(); establish("alice"); @@ -1383,8 +1445,8 @@ mod tests { } #[test] // [unit->REQ-SEAM-ACTIVITY] echo-gate set/clear is independent of idle. - // [unit->REQ-ECHO-IDLE-AGE-GATE] set arms the EDGE arm (explicit means NOW); - // clear clears BOTH, or it would leave the pending echo it promised to remove. + // [unit->REQ-ECHO-IDLE-AGE-GATE] set arms the EDGE arm (explicit means NOW); + // clear clears BOTH, or it would leave the pending echo it promised to remove. fn echo_gate_explicit_toggle() { let _h = isolated_home(); establish("alice"); @@ -1557,7 +1619,11 @@ mod tests { spool::spool_message_deferred_at(&perch_path, "alice", "deferred one").unwrap(); let rows = spool::peek_non_deferred_at(&perch_path).unwrap(); - assert_eq!(rows.len(), 1, "peek_non_deferred_at must exclude deferred rows"); + assert_eq!( + rows.len(), + 1, + "peek_non_deferred_at must exclude deferred rows" + ); assert!(rows[0].2.contains("live one")); // Marking delivered does not touch the deferred row. @@ -1585,15 +1651,30 @@ mod tests { establish("dave"); let perch_path = perch::resolve_perch_path("dave", ParentHint::Infer); spool::spool_message_windowed_at( - &perch_path, "x", "D", spool::WINDOW_DEFAULT, spool::CHANNEL_ANY, false, + &perch_path, + "x", + "D", + spool::WINDOW_DEFAULT, + spool::CHANNEL_ANY, + false, ) .unwrap(); spool::spool_message_windowed_at( - &perch_path, "x", "I", spool::WINDOW_IDLE_ONLY, spool::CHANNEL_ANY, false, + &perch_path, + "x", + "I", + spool::WINDOW_IDLE_ONLY, + spool::CHANNEL_ANY, + false, ) .unwrap(); spool::spool_message_windowed_at( - &perch_path, "x", "A", spool::WINDOW_ACTIVE_ONLY, spool::CHANNEL_ANY, false, + &perch_path, + "x", + "A", + spool::WINDOW_ACTIVE_ONLY, + spool::CHANNEL_ANY, + false, ) .unwrap(); @@ -1616,7 +1697,12 @@ mod tests { // active_only survived the active-no-include drain; the hook with // include_deferred takes it (resting gate aside). spool::spool_message_windowed_at( - &perch_path, "x", "A2", spool::WINDOW_ACTIVE_ONLY, spool::CHANNEL_ANY, false, + &perch_path, + "x", + "A2", + spool::WINDOW_ACTIVE_ONLY, + spool::CHANNEL_ANY, + false, ) .unwrap(); let with_def = poll_drain("dave", true); @@ -1749,7 +1835,10 @@ mod tests { assert_eq!(perch::read_activity_at(&perch_path), (true, None)); assert_eq!(cmd_state("legacy", "idle", true, None, false, false), 0); let (is_idle, since) = perch::read_activity_at(&perch_path); - assert!(is_idle && since.is_some(), "the idle direction is dated too"); + assert!( + is_idle && since.is_some(), + "the idle direction is dated too" + ); // ── A DISAGREEING stamp reads as undated (it describes the state we // left), so the same exception rewrites it in agreement — the endpoint @@ -1814,7 +1903,11 @@ mod tests { fn every_verdict_answers_the_exit_code_it_always_did() { use crate::cli::SendVerdict; - assert_eq!(SendVerdict::Delivered.code(), 0, "SENT and QUEUED both exited 0"); + assert_eq!( + SendVerdict::Delivered.code(), + 0, + "SENT and QUEUED both exited 0" + ); assert_eq!( SendVerdict::NoPerch.code(), 1, diff --git a/crates/spt/src/api/engineroom.rs b/crates/spt/src/api/engineroom.rs index ff8bb9f2..be2d7943 100644 --- a/crates/spt/src/api/engineroom.rs +++ b/crates/spt/src/api/engineroom.rs @@ -32,8 +32,8 @@ use spt_store::access::{AccessStore, Mode}; use spt_store::empower::{self, Empowerments}; -use spt_store::notif::NotifScope; use spt_store::engineroom::{self, EngineRoom, GateLedger, GateOutcome, Presented}; +use spt_store::notif::NotifScope; use spt_store::perch::{self, ParentHint}; use spt_store::subnet::SubnetStore; use spt_store::{atomic, info}; @@ -65,7 +65,11 @@ pub enum EngineRoomAuth { /// is missing rather than an auth failure it cannot fix. // [impl->REQ-SUBNET-EMPOWER-VERB] [impl->REQ-ACL-ACCESS-REFRESH-ER-ONLY] // [impl->REQ-ACL-NODE-MODE-SET] -pub fn classify(caller_is_engine_room: bool, provisioned: bool, auth: AuthResult) -> EngineRoomAuth { +pub fn classify( + caller_is_engine_room: bool, + provisioned: bool, + auth: AuthResult, +) -> EngineRoomAuth { if !caller_is_engine_room { return EngineRoomAuth::NotEngineRoom; } @@ -165,11 +169,15 @@ pub fn refuse(verdict: EngineRoomAuth, caller_id: &str) -> i32 { /// typed a code — loud, not silent, and never a foreign agent quietly seated at /// the controls of a room the operator believes is theirs. // [impl->REQ-ER-RESERVED-ID-SPAWN-REFUSAL] -pub fn reserved_bind_refusal(id: &str, engine_room_hosted: bool) -> Option { +pub fn reserved_bind_refusal( + id: &str, + engine_room_hosted: impl FnOnce() -> bool, +) -> Option { // One predicate, one sentence: the shared refusal, unchanged, so this seam // cannot drift its own spelling of the rule. let refusal = engineroom::reserved_id_refusal(id)?; - (!engine_room_hosted).then_some(refusal) + // Ordinary ids never need the broker probe or its refusal diagnostics. + (!engine_room_hosted()).then_some(refusal) } /// The observable behind [`reserved_bind_refusal`]: is this node's broker @@ -461,7 +469,9 @@ pub fn cmd_access_refresh(caller_id: &str, subnet: &str, proof: &Proof) -> i32 { // Subnet-scope authority comes from the subnet's admin key, not from being // the engine room — so this verb spends an empowerment. let Some(session_id) = caller_session_id(caller_id) else { - spt_proto::emit_line_err!("NO_SESSION:{caller_id} has no session recorded. Nothing was changed."); + spt_proto::emit_line_err!( + "NO_SESSION:{caller_id} has no session recorded. Nothing was changed." + ); return EXIT_REFUSED; }; if !Empowerments::load(&session_id).holds(subnet) { @@ -474,7 +484,9 @@ pub fn cmd_access_refresh(caller_id: &str, subnet: &str, proof: &Proof) -> i32 { let mut subnets = SubnetStore::load(); let Some(rec) = subnets.find(subnet) else { - spt_proto::emit_line_err!("NO_SUBNET:{subnet} — this node is not a member. Nothing was changed."); + spt_proto::emit_line_err!( + "NO_SUBNET:{subnet} — this node is not a member. Nothing was changed." + ); return EXIT_REFUSED; }; let held = rec.mode; @@ -633,7 +645,9 @@ pub fn cmd_access_node_surface_mode( spt_proto::emit_line_err!( "ACCESS_UNKNOWN_SURFACE:{surface} is not a control surface. The vocabulary is: \ {}. Nothing was changed.", - spt_store::access::surface::v1().collect::>().join(", ") + spt_store::access::surface::v1() + .collect::>() + .join(", ") ); return EXIT_REFUSED; }; @@ -890,29 +904,28 @@ mod tests { #[test] fn the_perch_minting_verbs_admit_the_reserved_id_only_as_a_completion() { let er = engineroom::ENGINE_ROOM_ID; - let refusal = reserved_bind_refusal(er, false).expect("a first mover is refused"); assert!( - refusal.contains("spt rc engine-room"), - "and the refusal names the ONE entry rather than only saying no: {refusal}" - ); - assert_eq!( - refusal, - engineroom::reserved_id_refusal(er).expect("the shared sentence"), - "one predicate, one sentence — this seam does not spell the rule its own way" + reserved_bind_refusal(er, || false).is_some(), + "a first mover is refused" ); assert_eq!( - reserved_bind_refusal(er, true), + reserved_bind_refusal(er, || true), None, "a hosted engine-room session means its bring-up already passed the gate, \ and this bind is that bring-up's completion" ); - for hosted in [true, false] { - assert_eq!( - reserved_bind_refusal("todlando", hosted), - None, - "an ordinary id is untouched at these verbs, hosted or not" - ); - } + } + + // [unit->REQ-ER-RESERVED-ID-SPAWN-REFUSAL] ordinary binds must not dial the + // engine-room probe or emit its unrelated refusal diagnostics (releases#279). + #[test] + fn ordinary_perch_minting_never_probes_the_engine_room() { + assert_eq!( + reserved_bind_refusal("todlando", || { + panic!("an ordinary id must not probe engine-room hosting") + }), + None + ); } /// A sessions reply holding exactly the rows and in-flight entries named. @@ -994,7 +1007,10 @@ mod tests { code_matches(&seed, &totp.code_at(now - period), now), "a code read one step ago still empowers (the phone-in-hand tolerance)" ); - assert!(code_matches(&seed, &totp.code_at(now + period), now), "and one ahead"); + assert!( + code_matches(&seed, &totp.code_at(now + period), now), + "and one ahead" + ); assert!( !code_matches(&seed, &totp.code_at(now - 3 * period), now), "but not one from outside the window" @@ -1006,7 +1022,11 @@ mod tests { "another subnet's key does not empower this one" ); // Trailing whitespace off a copy-paste is tolerated; a truncated code is not. - assert!(code_matches(&seed, &format!("{}\n", totp.code_at(now)), now)); + assert!(code_matches( + &seed, + &format!("{}\n", totp.code_at(now)), + now + )); assert!(!code_matches(&seed, &totp.code_at(now)[..5], now)); } @@ -1114,7 +1134,10 @@ mod tests { // The same holds however many times it tries — there is no counter to // ratchet, so the gate a human needs cannot be closed from here. for _ in 0..5 { - assert_eq!(cmd_empower("todlando", "bignet", "000000", &proof), EXIT_REFUSED); + assert_eq!( + cmd_empower("todlando", "bignet", "000000", &proof), + EXIT_REFUSED + ); } assert!(!ledger.exists()); } diff --git a/crates/spt/src/api/ioevents.rs b/crates/spt/src/api/ioevents.rs index c536a3f9..862c2767 100644 --- a/crates/spt/src/api/ioevents.rs +++ b/crates/spt/src/api/ioevents.rs @@ -140,7 +140,7 @@ pub fn poll( match read_cursor(session, owner) { None => { // THE SEED PATH. Silent by construction. - let head = iolog::last_seq_at(perch_path); + let head = iolog::read_after_at(perch_path, u64::MAX, None).head; write_cursor(session, owner, head); Poll { rows: Vec::new(), @@ -176,10 +176,9 @@ pub fn poll( /// a reader that refused the whole poll over one such row would turn a forward /// compatible record into a broken hook. fn read_bounded(perch_path: &std::path::Path, from: u64, limit: Option) -> Scan { - let all = iolog::read_after_at(perch_path, from, None); - // The highest seq this poll actually LOOKED AT, ignored rows included. See - // [`Scan::cursor`] for why that is not the same as the last row returned. - let scanned_to = all.last().map(|r| r.seq); + // Rows and the true head come from one locked snapshot. Even an oversized + // cursor must report where the log stands, not echo the caller's cursor. + let iolog::IoLogRead { rows: all, head } = iolog::read_after_at(perch_path, from, None); // The limit is applied AFTER the vocabulary filter, and `more` is measured // against what survived it — a page full of rows this binary would have // dropped is not a page, and reporting it as capped would send the adapter @@ -205,19 +204,15 @@ fn read_bounded(perch_path: &std::path::Path, from: u64, limit: Option) - if let Some(n) = limit { rows.truncate(n); } - Scan { - rows, - more, - scanned_to, - } + Scan { rows, more, head } } /// One read of the log: what it returns, and how far it got. struct Scan { rows: Vec, more: bool, - /// The highest seq examined, INCLUDING rows the vocabulary filter dropped. - scanned_to: Option, + /// Global maximum seq in the snapshot, independent of selection and limit. + head: u64, } impl Scan { @@ -226,20 +221,14 @@ impl Scan { /// **Capped: the last row HANDED OVER.** A poll that hit `--limit` must /// leave the rest for the next poll rather than skip them. /// - /// **Uncapped: the last row EXAMINED, not the last row returned.** These - /// differ exactly when the newest rows were dropped by the vocabulary - /// filter, and taking the last returned row there would pin the cursor - /// behind them — every later poll would re-read a growing tail of rows it - /// has already decided to ignore. Nothing emits an unknown kind today, so - /// this is the FORWARD-COMPATIBILITY path: it is reached when a newer core - /// writes a kind this binary does not know, which is the whole scenario the - /// ignore-rather-than-refuse posture exists to survive. A stall there would - /// turn graceful degradation into a slow leak. + /// **Uncapped: the snapshot's true head**, including rows ignored by the + /// vocabulary filter or excluded by an oversized incoming cursor. Reporting + /// a lower head lets a persisted pre-reset cursor recover on the next poll. fn cursor(&self, from: u64) -> u64 { if self.more { return self.rows.last().map(|r| r.seq).unwrap_or(from); } - self.scanned_to.unwrap_or(from) + self.head } } @@ -297,9 +286,20 @@ pub fn render_text(p: &Poll) -> String { } let mut out = String::new(); for r in &p.rows { - let peer = r.peer.as_deref().map(|x| format!(" peer={x}")).unwrap_or_default(); + let peer = r + .peer + .as_deref() + .map(|x| format!(" peer={x}")) + .unwrap_or_default(); let trunc = if r.truncated { " (truncated)" } else { "" }; - let head: String = r.payload.lines().next().unwrap_or("").chars().take(120).collect(); + let head: String = r + .payload + .lines() + .next() + .unwrap_or("") + .chars() + .take(120) + .collect(); out.push_str(&format!("{} {}{}{} {}\n", r.seq, r.kind, peer, trunc, head)); } if p.more { @@ -428,7 +428,11 @@ mod tests { let second = poll(&d, Some(&sid), "owner", None, None); assert!(!second.seeded); assert_eq!( - second.rows.iter().map(|r| r.payload.as_str()).collect::>(), + second + .rows + .iter() + .map(|r| r.payload.as_str()) + .collect::>(), vec!["after"], "the second poll is NON-VACUOUS — without this the first assertion proves nothing" ); @@ -479,7 +483,10 @@ mod tests { let p = poll(&d, Some(&sid), "owner", Some(1), None); assert!(!p.seeded, "an explicit cursor never seeds"); assert_eq!( - p.rows.iter().map(|r| r.payload.as_str()).collect::>(), + p.rows + .iter() + .map(|r| r.payload.as_str()) + .collect::>(), vec!["b", "c"] ); assert!( @@ -488,17 +495,61 @@ mod tests { ); } + // [unit->REQ-IO-EVENT-POLL-VERB] + #[test] + fn an_oversized_cursor_reports_the_true_head() { + let d = tmp("above-head"); + put(&d, IO_KIND_USER_INPUT, "first"); + put(&d, IO_KIND_AGENT_OUTPUT, "second"); + let p = poll(&d, None, "owner", Some(3), None); + assert!(p.rows.is_empty()); + assert_eq!(p.cursor, 2, "an empty answer reports the head, not --after"); + let empty = tmp("above-empty-head"); + assert_eq!(poll(&empty, None, "owner", Some(3), None).cursor, 0); + } + + // [unit->REQ-IO-EVENT-POLL-VERB] + #[test] + fn a_session_cursor_above_head_recovers_for_the_next_event() { + let _home = crate::testutil::isolated_home(); + let d = tmp("recover-head"); + let sid = format!("sid-recover-head-{}", std::process::id()); + put(&d, IO_KIND_USER_INPUT, "before"); + write_cursor(&sid, "owner", 99999); + let quiet = poll(&d, Some(&sid), "owner", None, None); + assert!(quiet.rows.is_empty()); + assert_eq!(quiet.cursor, 1); + put(&d, IO_KIND_AGENT_OUTPUT, "after recovery"); + let next = poll(&d, Some(&sid), "owner", None, None); + assert_eq!(next.cursor, 2); + assert_eq!( + next.rows + .iter() + .map(|r| r.payload.as_str()) + .collect::>(), + vec!["after recovery"] + ); + let _ = std::fs::remove_dir_all(perch::session_dir(&sid)); + } + // [unit->REQ-IO-EVENT-POLL-VERB] an unknown kind is IGNORED, not refused — // the poll still answers with the rows around it. #[test] fn an_unknown_kind_is_ignored_not_refused() { let d = tmp("unknown"); put(&d, IO_KIND_USER_INPUT, "known one"); - put(&d, "SOMETHING_FROM_THE_FUTURE", "not in this binary's vocabulary"); + put( + &d, + "SOMETHING_FROM_THE_FUTURE", + "not in this binary's vocabulary", + ); put(&d, IO_KIND_AGENT_OUTPUT, "known two"); let p = poll(&d, None, "owner", Some(0), None); assert_eq!( - p.rows.iter().map(|r| r.payload.as_str()).collect::>(), + p.rows + .iter() + .map(|r| r.payload.as_str()) + .collect::>(), vec!["known one", "known two"], "the unknown row is skipped and its neighbours still arrive" ); @@ -545,7 +596,11 @@ mod tests { let first = poll(&d, Some(&sid), "owner", None, None); assert_eq!( - first.rows.iter().map(|r| r.payload.as_str()).collect::>(), + first + .rows + .iter() + .map(|r| r.payload.as_str()) + .collect::>(), vec!["also known"], "the known row arrives: {:?}", first.rows @@ -582,13 +637,21 @@ mod tests { let first = poll(&d, Some(&sid), "owner", None, Some(2)); assert_eq!( - first.rows.iter().map(|r| r.payload.as_str()).collect::>(), + first + .rows + .iter() + .map(|r| r.payload.as_str()) + .collect::>(), vec!["e", "f"] ); assert!(first.more, "the cap is DECLARED, never silent"); let second = poll(&d, Some(&sid), "owner", None, Some(2)); assert_eq!( - second.rows.iter().map(|r| r.payload.as_str()).collect::>(), + second + .rows + .iter() + .map(|r| r.payload.as_str()) + .collect::>(), vec!["g"], "the row the cap deferred is the next poll's first row, not a lost one" ); @@ -610,7 +673,11 @@ mod tests { assert_eq!(v["cursor"], 7); assert_eq!(v["seeded"], true); assert_eq!(v["events"].as_array().unwrap().len(), 0); - assert_eq!(render_text(&empty), "", "the TEXT surface stays silent, though"); + assert_eq!( + render_text(&empty), + "", + "the TEXT surface stays silent, though" + ); let loud = Poll { rows: vec![IoLogRow { diff --git a/crates/spt/src/api/live.rs b/crates/spt/src/api/live.rs index 684df955..5589fb44 100644 --- a/crates/spt/src/api/live.rs +++ b/crates/spt/src/api/live.rs @@ -56,7 +56,8 @@ pub fn cmd_shutdown(id: &str, manifest: Option<&Manifest>, install_dir: Option<& Ok(outcome) => { spt_proto::emit_line_err!( "SHUTDOWN:{id} echo_ran={} signed_off={}", - outcome.echo_ran, outcome.signed_off + outcome.echo_ran, + outcome.signed_off ); 0 } diff --git a/crates/spt/src/api/mod.rs b/crates/spt/src/api/mod.rs index 5440d5d4..d78902f3 100644 --- a/crates/spt/src/api/mod.rs +++ b/crates/spt/src/api/mod.rs @@ -709,7 +709,9 @@ pub fn run(args: ApiArgs, json: bool) -> i32 { 0 } None => { - spt_proto::emit_line_err!("BIND_SHELL_REFUSED: no instance holds this link token"); + spt_proto::emit_line_err!( + "BIND_SHELL_REFUSED: no instance holds this link token" + ); EXIT_REFUSED } } @@ -747,11 +749,11 @@ pub fn run(args: ApiArgs, json: bool) -> i32 { // invocation is named as ambiguous rather than as unauthorized — // a caller who passed both sources has a usage bug, and telling // them "denied" would send them hunting the wrong thing. - let payload = match delivery::resolve_state_payload(payload_stdin, payload_file.as_deref()) - { - Ok(p) => p, - Err(code) => return code, - }; + let payload = + match delivery::resolve_state_payload(payload_stdin, payload_file.as_deref()) { + Ok(p) => p, + Err(code) => return code, + }; // [impl->REQ-IO-MIDTURN-SPAN] refused BEFORE the auth gate for the // same reason the payload sources are: a caller who wrote a // contradiction has a usage bug, and answering `denied` would send @@ -763,10 +765,7 @@ pub fn run(args: ApiArgs, json: bool) -> i32 { // manifest of the adapter making the call, and a call with no // manifest at all is ungated-off: absent declaration, absent // permission. `Manifest::shortform_enabled` holds both rulings. - let shortform = ctx - .manifest - .as_ref() - .is_some_and(|m| m.shortform_enabled()); + let shortform = ctx.manifest.as_ref().is_some_and(|m| m.shortform_enabled()); gated(&id, &auth, |id| { delivery::cmd_state(id, &state, no_gate, payload.as_deref(), shortform, mid) }) @@ -830,11 +829,9 @@ pub fn run(args: ApiArgs, json: bool) -> i32 { // Resume-context pull (REQ-RESUME-CONTEXT-PULL): auth-gated like the sibling // id-scoped verbs; session_id is accepted for the adapter contract but the // Tier-1 handler resolves project context from the perch's bound cwd. - ApiCmd::PsycheDownload { id, auth } => { - gated(&id, &auth, |id| { - reporting::cmd_psyche_download(id, ctx.manifest.as_ref()) - }) - } + ApiCmd::PsycheDownload { id, auth } => gated(&id, &auth, |id| { + reporting::cmd_psyche_download(id, ctx.manifest.as_ref()) + }), ApiCmd::DrivenBy { id, auth } => gated(&id, &auth, reporting::cmd_driven_by), // Read-only JSON report; the bare form self-resolves like whoami, so it takes // no auth (no mutation, exposes only what `endpoint list` already shows). @@ -970,10 +967,9 @@ fn resolve_ctx_manifest( // adapter (no record) degrades to `(None, None)`, unchanged. let adapters_dir = spt_store::perch::adapters_dir(); match spt_runtime::registry::resolve_option(&adapters_dir, adapter) { - Ok((record, manifest)) => Ok(( - Some(manifest), - Some(PathBuf::from(&record.source_dir)), - )), + Ok((record, manifest)) => { + Ok((Some(manifest), Some(PathBuf::from(&record.source_dir)))) + } Err(_) => Ok((None, None)), } } @@ -1022,11 +1018,15 @@ fn gated i32>(target_id: &str, auth: &AuthFlags, f: F) -> i32 match authenticate(target_id, &auth.proof()) { AuthResult::Ok => f(target_id), AuthResult::NoEndpoint => { - spt_proto::emit_line_err!("NO_ENDPOINT:{target_id} has no perch to authenticate against"); + spt_proto::emit_line_err!( + "NO_ENDPOINT:{target_id} has no perch to authenticate against" + ); EXIT_REFUSED } AuthResult::Refused => { - spt_proto::emit_line_err!("AUTH_REFUSED:{target_id} (need --token or matching --session-id)"); + spt_proto::emit_line_err!( + "AUTH_REFUSED:{target_id} (need --token or matching --session-id)" + ); EXIT_REFUSED } } @@ -1041,7 +1041,9 @@ fn worker_gated i32>(target_id: &str, auth: &AuthFlags, f: F) match worker_authenticate(target_id, &auth.proof()) { AuthResult::Ok => f(target_id), AuthResult::NoEndpoint => { - spt_proto::emit_line_err!("NO_ENDPOINT:{target_id} has no perch to authenticate against"); + spt_proto::emit_line_err!( + "NO_ENDPOINT:{target_id} has no perch to authenticate against" + ); EXIT_REFUSED } AuthResult::Refused => { @@ -1169,7 +1171,8 @@ mod tests { .unwrap(); let (manifest, install_dir) = - resolve_ctx_manifest(Some(path.as_path()), Some("mock-h:full")).expect("override resolves"); + resolve_ctx_manifest(Some(path.as_path()), Some("mock-h:full")) + .expect("override resolves"); let m = manifest.expect("override yields a manifest"); assert_eq!(m.adapter.hostable_types, vec!["LiveAgent", "Shell"]); assert_eq!(install_dir.as_deref(), Some(dir.as_path())); @@ -1181,9 +1184,12 @@ mod tests { #[test] fn ctx_manifest_unregistered_no_manifest_is_none_not_fatal() { let _h = crate::testutil::isolated_home(); - let (manifest, install_dir) = - resolve_ctx_manifest(None, Some("ghost:full")).expect("unregistered does not hard-fail"); - assert!(manifest.is_none(), "no manifest for an unregistered adapter"); + let (manifest, install_dir) = resolve_ctx_manifest(None, Some("ghost:full")) + .expect("unregistered does not hard-fail"); + assert!( + manifest.is_none(), + "no manifest for an unregistered adapter" + ); assert!(install_dir.is_none(), "no install_dir either"); } @@ -1351,19 +1357,44 @@ mod tests { ); // [unit->REQ-SHELL-3] drive-poll is the shell-side drain; the link is the // auth (mirrors emit), and it is mandatory. - assert!(parse(&["spt", "--adapter", "m", "drive-poll", "shell-0", "--link", "cafe"]).is_ok()); + assert!(parse(&[ + "spt", + "--adapter", + "m", + "drive-poll", + "shell-0", + "--link", + "cafe" + ]) + .is_ok()); assert!( parse(&["spt", "--adapter", "m", "drive-poll", "shell-0"]).is_err(), "drive-poll requires the link credential" ); // [unit->REQ-SHELL-4] the shell-side tunnel verb: id + direction + the link // token (the auth, mirrors drive-poll); the link is mandatory. - assert!( - parse(&["spt", "--adapter", "m", "tunnel", "shell-0", "recv", "--link", "cafe"]).is_ok() - ); - assert!( - parse(&["spt", "--adapter", "m", "tunnel", "shell-0", "send", "--link", "cafe"]).is_ok() - ); + assert!(parse(&[ + "spt", + "--adapter", + "m", + "tunnel", + "shell-0", + "recv", + "--link", + "cafe" + ]) + .is_ok()); + assert!(parse(&[ + "spt", + "--adapter", + "m", + "tunnel", + "shell-0", + "send", + "--link", + "cafe" + ]) + .is_ok()); assert!( parse(&["spt", "--adapter", "m", "tunnel", "shell-0", "recv"]).is_err(), "the shell tunnel verb requires the link credential" @@ -1378,8 +1409,15 @@ mod tests { ); // Optional adapter correlation metadata is accepted. assert!(parse(&[ - "spt", "--adapter", "m", "worker-start", "alice", "--agent-id", "cc-3f2a", - "--agent-type", "code-reviewer" + "spt", + "--adapter", + "m", + "worker-start", + "alice", + "--agent-id", + "cc-3f2a", + "--agent-type", + "code-reviewer" ]) .is_ok()); assert!(parse(&[ diff --git a/crates/spt/src/api/nowsignal.rs b/crates/spt/src/api/nowsignal.rs index 90edf2c8..4dde7bd7 100644 --- a/crates/spt/src/api/nowsignal.rs +++ b/crates/spt/src/api/nowsignal.rs @@ -36,8 +36,8 @@ use std::path::{Path, PathBuf}; use spt_store::perch; -use super::Ctx; use super::reporting; +use super::Ctx; /// The wall clock in epoch-ms, or 0 if the clock is before the epoch. /// @@ -487,7 +487,8 @@ fn gather_shell_hints(input: &PollInput, text: &str) -> Vec { let mut out = Vec::new(); for (adapter, (option, arm)) in sources { - let Ok((_, manifest)) = spt_runtime::registry::resolve_option(&adapters_dir, &option) else { + let Ok((_, manifest)) = spt_runtime::registry::resolve_option(&adapters_dir, &option) + else { continue; // deregistered or unreadable — silence, not a diagnostic }; if manifest.adapter.kind != AdapterKind::Shell || manifest.hints.is_empty() { @@ -733,7 +734,10 @@ pub fn gather_edge_transitions( // [impl->REQ-NOW-SIGNAL-EDGE-SUBJECT-NAMING] fn subnet_join_line(label: &str, pubkey_hex: &str, subnet: &str) -> String { let who = if label.is_empty() { - format!("pubkey {}…", pubkey_hex.chars().take(12).collect::()) + format!( + "pubkey {}…", + pubkey_hex.chars().take(12).collect::() + ) } else { label.to_string() }; @@ -833,13 +837,15 @@ pub fn gather_updates(ctx: &Ctx, input: &PollInput, seen: &mut SeenSet) -> Vec Vec { /// The brief itself — two sentences, held as one constant so the wording has a /// single home and the two-sentence bound is auditable at a glance. // [impl->REQ-NOW-SIGNAL-SEAL-BRIEF] -pub const SEAL_BRIEF_TEXT: &str = "A sealed message is a PROVEN USER DIRECTIVE: the seal is cryptographic evidence the words \ +pub const SEAL_BRIEF_TEXT: &str = + "A sealed message is a PROVEN USER DIRECTIVE: the seal is cryptographic evidence the words \ came from your operator, not from another agent quoting them. Verify one with `spt api \ seal verify ` (the content goes on stdin), and mint your own by wrapping the text \ in `;;like this;;`."; @@ -960,13 +967,12 @@ pub fn cmd_now_signal( // The endpoint roster is read ONCE and shared: two categories want it, and // this is a per-turn hook where a second gather is a second full walk of the // registry and the gossip snapshots. - let rows: Vec = if spec.allows(Category::EndpointMentions) - || spec.allows(Category::EdgeTransitions) - { - crate::picker::data::gather_endpoints() - } else { - Vec::new() - }; + let rows: Vec = + if spec.allows(Category::EndpointMentions) || spec.allows(Category::EdgeTransitions) { + crate::picker::data::gather_endpoints() + } else { + Vec::new() + }; let mut blocks = Vec::new(); for cat in Category::all() { @@ -1060,7 +1066,10 @@ mod tests { .map(|k| k.to_string()) .collect(); seen.flush(); - assert!(second.is_empty(), "nothing new — the category contributes nothing"); + assert!( + second.is_empty(), + "nothing new — the category contributes nothing" + ); assert_eq!( compose(&[Block { category: Category::Shells, @@ -1180,9 +1189,8 @@ mod tests { // [unit->REQ-NOW-SIGNAL-SPEC] #[test] fn a_spec_selects_from_the_closed_vocabulary_and_ignores_the_rest() { - let spec = NowSpec::from_json( - r#"{"only":["HINTS","PROJECTS","not_a_category"],"max_lines":2}"#, - ); + let spec = + NowSpec::from_json(r#"{"only":["HINTS","PROJECTS","not_a_category"],"max_lines":2}"#); assert_eq!( spec.only, vec![Category::Hints], @@ -1244,7 +1252,11 @@ mod tests { .to_string_lossy() .contains(cat.tag())); } - assert_eq!(Category::V1.len(), 7, "the v1 vocabulary is CLOSED at seven"); + assert_eq!( + Category::V1.len(), + 7, + "the v1 vocabulary is CLOSED at seven" + ); assert!( Category::all() .take(Category::V1.len()) diff --git a/crates/spt/src/api/reporting.rs b/crates/spt/src/api/reporting.rs index 7ce9c43e..c10f1e4e 100644 --- a/crates/spt/src/api/reporting.rs +++ b/crates/spt/src/api/reporting.rs @@ -351,8 +351,12 @@ pub(super) fn resurface_notifs_with(id: &str, manifest: Option<&Manifest>) { for notif_id in surfaced { if let Ok(Some(row)) = store.get(notif_id) { match spt_daemon::notif::spawn_notif_command(&runtime, &row) { - Ok(pid) => spt_proto::emit_line_err!("NOTIF_COMMAND:{notif_id} pid={pid}"), - Err(e) => spt_proto::emit_line_err!("NOTIF_COMMAND_FAIL:{notif_id}: {e}"), + Ok(pid) => { + spt_proto::emit_line_err!("NOTIF_COMMAND:{notif_id} pid={pid}") + } + Err(e) => { + spt_proto::emit_line_err!("NOTIF_COMMAND_FAIL:{notif_id}: {e}") + } } } } @@ -723,7 +727,9 @@ pub fn cmd_tunnel(id: &str, direction: &str, link: &str) -> i32 { ) { Ok(Some(s)) => s, Ok(None) => { - spt_proto::emit_line_err!("NO_TUNNEL:{shell_id}: no live tunnel (declare [shell.tunnel] + relink)"); + spt_proto::emit_line_err!( + "NO_TUNNEL:{shell_id}: no live tunnel (declare [shell.tunnel] + relink)" + ); return EXIT_REFUSED; } Err(e) => { @@ -768,7 +774,9 @@ pub fn cmd_tunnel(id: &str, direction: &str, link: &str) -> i32 { } }, other => { - spt_proto::emit_line_err!("USAGE: api tunnel --link (got '{other}')"); + spt_proto::emit_line_err!( + "USAGE: api tunnel --link (got '{other}')" + ); 2 } } @@ -792,11 +800,15 @@ pub fn cmd_owner_shutdown(id: &str, link: &str) -> i32 { return EXIT_REFUSED; }; if shell_id != id { - spt_proto::emit_line_err!("OWNER_SHUTDOWN_REFUSED:{id}: the link token belongs to {shell_id}"); + spt_proto::emit_line_err!( + "OWNER_SHUTDOWN_REFUSED:{id}: the link token belongs to {shell_id}" + ); return EXIT_REFUSED; } let Some(node) = spt_store::nodeid::load_existing().map(|i| i.public_key().to_hex()) else { - spt_proto::emit_line_err!("OWNER_SHUTDOWN_REFUSED:{shell_id}: no node identity — no grant can exist"); + spt_proto::emit_line_err!( + "OWNER_SHUTDOWN_REFUSED:{shell_id}: no node identity — no grant can exist" + ); return EXIT_REFUSED; }; match grants::check(&owlery, grants::CAP_OWNER_SHUTDOWN, &shell_id, &node, None) { @@ -813,7 +825,8 @@ pub fn cmd_owner_shutdown(id: &str, link: &str) -> i32 { Ok(Some(report)) => { spt_proto::emit_line_err!( "OWNER_SHUTDOWN:{owner} by {shell_id} ({:?} -> {:?})", - report.from, report.to + report.from, + report.to ); 0 } @@ -877,9 +890,7 @@ pub fn resolve_filedrops( // (An absolute manifest dir resolves identically both ways, so this can // only fire for a relative dir under a different cwd.) let caller = resolve_endpoint_drop_dir(raw, caller_cwd).map(|d| d.join(&name)); - if let Some(path) = caller - .filter(|c| c.is_file() && Some(c) != registered.as_ref()) - { + if let Some(path) = caller.filter(|c| c.is_file() && Some(c) != registered.as_ref()) { return Some(ResolvedDrop { path, anchor: DropAnchor::Misplaced, @@ -966,8 +977,12 @@ pub fn cmd_psyche_download(id: &str, manifest: Option<&Manifest>) -> i32 { // brief's bytes are unchanged. With no brief at all there is nothing to // qualify, so it joins the stderr notices instead. // [impl->REQ-PSYCHE-INGEST-FAULT-BRIEF-WARN] - let ingest_fault = - spt_live::ingest_fault_notice(id, info::read_info(&perch_path).and_then(|rec| rec.psyche_host_error).as_ref()); + let ingest_fault = spt_live::ingest_fault_notice( + id, + info::read_info(&perch_path) + .and_then(|rec| rec.psyche_host_error) + .as_ref(), + ); match spt_live::download_psyche_context( id, &project_id, @@ -1270,7 +1285,10 @@ fn derive_attached_node( // Own-node driver (a same-node rc through the net path) self-attributes to THIS // node, exactly like the local-controller arm — never a foreign null-label hex. Some(driver) if crate::roster::is_own_node_hex(driver, Some(self_key)) => { - Some(NodeRefJson { label: self_label, key: self_key.to_string() }) + Some(NodeRefJson { + label: self_label, + key: self_key.to_string(), + }) } Some(remote) => Some(NodeRefJson { label: resolve_label(remote), @@ -1289,7 +1307,9 @@ fn derive_attached_node( /// `None` when no peer has advertised a label for it. // [impl->REQ-API-ENDPOINT-INFO] pub(crate) fn resolve_node_label(node_hex: &str) -> Option { - registry_node_label_map().get(&node_hex.to_lowercase()).cloned() + registry_node_label_map() + .get(&node_hex.to_lowercase()) + .cloned() } /// The gossiped registry's whole hex-to-label table — the CLI-side companion @@ -1324,7 +1344,9 @@ pub fn cmd_endpoint_info(id: Option<&str>) -> i32 { .map(str::to_string) .or_else(crate::roster::detect_self_id) else { - spt_proto::emit_line_err!("NO_SELF: no given and this session resolves no local perch"); + spt_proto::emit_line_err!( + "NO_SELF: no given and this session resolves no local perch" + ); return EXIT_REFUSED; }; let perch_path = perch::resolve_perch_path(&id, ParentHint::Infer); @@ -1353,11 +1375,9 @@ pub fn cmd_endpoint_info(id: Option<&str>) -> i32 { // precisely because this used to run the git derivation; now it never // spawns git). Absent/stale → None, same '-' semantics. // [impl->REQ-PROJECT-INDEX-READER-CUTOVER] - let project = crate::picker::data::indexed_latest_project_ref( - &spt_store::projindex::read_index(), - &id, - ) - .map(|r| r.id); + let project = + crate::picker::data::indexed_latest_project_ref(&spt_store::projindex::read_index(), &id) + .map(|r| r.id); let subnets = spt_store::subnet::SubnetStore::load() .subnets .iter() @@ -1389,7 +1409,10 @@ pub fn cmd_endpoint_info(id: Option<&str>) -> i32 { 0 } Err(e) => { - spt_proto::emit_line_err!("ENDPOINT_INFO_ENCODE_FAIL:{id_err}: {e}", id_err = payload.id); + spt_proto::emit_line_err!( + "ENDPOINT_INFO_ENCODE_FAIL:{id_err}: {e}", + id_err = payload.id + ); EXIT_REFUSED } } @@ -1426,13 +1449,19 @@ mod tests { ); assert_eq!( remote, - Some(NodeRefJson { label: Some("PEER".into()), key: "cafe1234".into() }), + Some(NodeRefJson { + label: Some("PEER".into()), + key: "cafe1234".into() + }), ); // Local controller (controlled, no remote driver): names THIS node. let local = derive_attached_node(None, true, "selfhex", Some("SELF".into()), |_| None); assert_eq!( local, - Some(NodeRefJson { label: Some("SELF".into()), key: "selfhex".into() }), + Some(NodeRefJson { + label: Some("SELF".into()), + key: "selfhex".into() + }), "a local controller surfaces via `controlled`, not driven_by", ); // Uncontrolled: null. @@ -1459,7 +1488,10 @@ mod tests { ); assert_eq!( own, - Some(NodeRefJson { label: Some("SELF".into()), key: "selfhex".into() }), + Some(NodeRefJson { + label: Some("SELF".into()), + key: "selfhex".into() + }), "an own-node driver self-attributes to THIS node, not a foreign hex", ); // A genuinely remote driver is unaffected — verbatim key + resolved label. @@ -1472,7 +1504,10 @@ mod tests { ); assert_eq!( remote, - Some(NodeRefJson { label: Some("PEER".into()), key: "cafe1234".into() }), + Some(NodeRefJson { + label: Some("PEER".into()), + key: "cafe1234".into() + }), ); } @@ -1493,7 +1528,11 @@ mod tests { info::write_info(&path, &rec).unwrap(); assert_eq!(cmd_endpoint_info(Some("alice")), 0, "seeded perch reports"); - assert_eq!(cmd_endpoint_info(Some("ghost")), EXIT_REFUSED, "unknown id refused"); + assert_eq!( + cmd_endpoint_info(Some("ghost")), + EXIT_REFUSED, + "unknown id refused" + ); } // [unit->REQ-ACTIVITY-INFO-PULL] ADR-0048 decision 1, pull avenue: `activity` is @@ -1510,7 +1549,10 @@ mod tests { adapter: None, controlled: false, attached_node: None, - local_node: NodeRefJson { label: None, key: "selfhex".into() }, + local_node: NodeRefJson { + label: None, + key: "selfhex".into(), + }, project: None, cwd: None, subnets: Vec::new(), @@ -1543,9 +1585,16 @@ mod tests { // Fresh perch: nothing has reported idle → busy (the working state). let idle_file = perch::resolve_idle_file("alice", ParentHint::Infer); - assert!(!idle_file.exists(), "PRECONDITION: no sentinel on a fresh perch"); + assert!( + !idle_file.exists(), + "PRECONDITION: no sentinel on a fresh perch" + ); assert_eq!(perch::activity_label_at(&path), "busy"); - assert_eq!(cmd_endpoint_info(Some("alice")), 0, "a busy endpoint reports"); + assert_eq!( + cmd_endpoint_info(Some("alice")), + 0, + "a busy endpoint reports" + ); // The adapter reports idle → the sentinel appears → the pull says idle. std::fs::write(&idle_file, "").unwrap(); @@ -1554,7 +1603,11 @@ mod tests { "idle", "REQ-ACTIVITY-INFO-PULL: the sentinel is the only input to the word" ); - assert_eq!(cmd_endpoint_info(Some("alice")), 0, "an idle endpoint reports too"); + assert_eq!( + cmd_endpoint_info(Some("alice")), + 0, + "an idle endpoint reports too" + ); // Back to work → the sentinel clears → the word flips back. No latch. std::fs::remove_file(&idle_file).unwrap(); @@ -1629,7 +1682,10 @@ mod tests { "an ordinary boundary rotates normally despite a custody record on the node" ); let rec = info::read_info(&perch::resolve_perch_path("victim", ParentHint::Infer)).unwrap(); - assert_eq!(rec.session_id, "fresh-sid", "the fresh sid rotates the perch pin"); + assert_eq!( + rec.session_id, "fresh-sid", + "the fresh sid rotates the perch pin" + ); } // [unit->REQ-TERM-6] a boundary appends the rotated session to the perch's @@ -1648,7 +1704,10 @@ mod tests { assert_eq!(rows[0].session_id, "sid-1"); assert_eq!(rows[0].trigger, spt_store::sessions::SessionTrigger::Clear); assert_eq!(rows[1].session_id, "sid-2"); - assert_eq!(rows[1].trigger, spt_store::sessions::SessionTrigger::Compact); + assert_eq!( + rows[1].trigger, + spt_store::sessions::SessionTrigger::Compact + ); } // [unit->REQ-ECHO-BOUNDARY-INPUT-BEFORE-ROTATION] a boundary leaves an echo @@ -1699,9 +1758,13 @@ mod tests { let perch = perch::resolve_perch_path("alice", ParentHint::Infer); assert_eq!(cmd_boundary("alice", "clear", "sid-1"), 0); assert_eq!(cmd_boundary("alice", "compact", "sid-2"), 0); - let rows = spt_store::iolog::read_after_at(&perch, 0, None); + let rows = spt_store::iolog::read_after_at(&perch, 0, None).rows; let kinds: Vec<&str> = rows.iter().map(|r| r.kind.as_str()).collect(); - assert_eq!(kinds, vec!["clear", "compact"], "one row per edge, in order"); + assert_eq!( + kinds, + vec!["clear", "compact"], + "one row per edge, in order" + ); for r in &rows { assert!(r.payload.is_empty(), "a boundary carries no payload: {r:?}"); assert!(!r.truncated, "nothing to truncate"); @@ -1720,7 +1783,7 @@ mod tests { let perch = perch::resolve_perch_path("alice", ParentHint::Infer); assert_eq!(cmd_boundary("alice", "compact", "sid-1"), 0); assert_eq!(cmd_boundary("alice", "wharrgarbl", "sid-2"), 0); - let rows = spt_store::iolog::read_after_at(&perch, 0, None); + let rows = spt_store::iolog::read_after_at(&perch, 0, None).rows; let kinds: Vec<&str> = rows.iter().map(|r| r.kind.as_str()).collect(); assert_eq!(kinds, vec!["compact", "clear"]); assert!( @@ -1730,7 +1793,10 @@ mod tests { // And the funnel agrees with the ledger written by the same call — // they are meant to be one fact, recorded twice. let ledger = spt_store::sessions::read_all(&perch); - assert_eq!(ledger[1].trigger, spt_store::sessions::SessionTrigger::Clear); + assert_eq!( + ledger[1].trigger, + spt_store::sessions::SessionTrigger::Clear + ); } // [unit->REQ-IO-BOUNDARY-EVENTS] ONE EVENT PER REAL BOUNDARY: a re-report of @@ -1745,8 +1811,12 @@ mod tests { establish("alice", "sid-old"); let perch = perch::resolve_perch_path("alice", ParentHint::Infer); assert_eq!(cmd_boundary("alice", "clear", "sid-1"), 0); - assert_eq!(cmd_boundary("alice", "clear", "sid-1"), 0, "still a success"); - let rows = spt_store::iolog::read_after_at(&perch, 0, None); + assert_eq!( + cmd_boundary("alice", "clear", "sid-1"), + 0, + "still a success" + ); + let rows = spt_store::iolog::read_after_at(&perch, 0, None).rows; assert_eq!(rows.len(), 1, "the re-bind crossed no edge: {rows:?}"); assert_eq!(spt_store::sessions::read_all(&perch).len(), 1); } @@ -1760,7 +1830,9 @@ mod tests { establish("alice", "sid-old"); // This node is a member of `home` (the resurface scope). let mut subnets = spt_store::subnet::SubnetStore::load(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); // One undismissed notif in the canonical store. let store = spt_store::notif::NotifStore::open().unwrap(); @@ -1831,12 +1903,16 @@ mod tests { let all = spt_store::spool::drain_all_at(&perch_path).unwrap(); assert_eq!(all.len(), 1, "{all:?}"); assert!( - all[0].body.contains("Scout → mock-shell-0 (mock-shell), offline"), + all[0] + .body + .contains("Scout → mock-shell-0 (mock-shell), offline"), "{:?}", all[0] ); assert!( - all[0].body.contains("instantiable shell adapters on this node"), + all[0] + .body + .contains("instantiable shell adapters on this node"), "{:?}", all[0] ); @@ -1993,7 +2069,10 @@ mod tests { 0 ); assert_eq!( - ingest_digest_entry("alice", r#"{"role":"tool","tool":{"name":"Write","arg":"a"}}"#), + ingest_digest_entry( + "alice", + r#"{"role":"tool","tool":{"name":"Write","arg":"a"}}"# + ), 0 ); let log = std::fs::read_to_string(perch.join("digest.log")).unwrap(); @@ -2089,12 +2168,7 @@ mod tests { // The drop sits ONLY in the worktree the caller is running in. The ingest // watches `registered` and will never see it — but the brief must. let stray = write(&worktree); - let (commune, _) = resolve_filedrops( - Some(&m), - "alice", - Some(®istered), - Some(&worktree), - ); + let (commune, _) = resolve_filedrops(Some(&m), "alice", Some(®istered), Some(&worktree)); let commune = commune.expect("a resolved drop"); assert_eq!( commune.anchor, @@ -2106,12 +2180,7 @@ mod tests { // Same call, drop in the REGISTERED dir instead: pending, not misplaced. std::fs::remove_file(&stray).unwrap(); let proper = write(®istered); - let (commune, _) = resolve_filedrops( - Some(&m), - "alice", - Some(®istered), - Some(&worktree), - ); + let (commune, _) = resolve_filedrops(Some(&m), "alice", Some(®istered), Some(&worktree)); let commune = commune.expect("a resolved drop"); assert_eq!( commune.anchor, @@ -2123,12 +2192,7 @@ mod tests { // BOTH present: the watched dir wins. Otherwise a stale worktree copy would // shadow the drop that is actually about to become the durable tier. let stray = write(&worktree); - let (commune, _) = resolve_filedrops( - Some(&m), - "alice", - Some(®istered), - Some(&worktree), - ); + let (commune, _) = resolve_filedrops(Some(&m), "alice", Some(®istered), Some(&worktree)); let commune = commune.expect("a resolved drop"); assert_eq!(commune.anchor, DropAnchor::Registered); assert_eq!(commune.path, proper); @@ -2214,10 +2278,20 @@ mod tests { let a = shell("shell-a"); let b = shell("shell-b"); - let line_a = - select_and_mark_shell_hint(&a, "sess-1", "please capture", "shell-a", ShellHintArm::Full); - let line_b = - select_and_mark_shell_hint(&b, "sess-1", "please capture", "shell-b", ShellHintArm::Full); + let line_a = select_and_mark_shell_hint( + &a, + "sess-1", + "please capture", + "shell-a", + ShellHintArm::Full, + ); + let line_b = select_and_mark_shell_hint( + &b, + "sess-1", + "please capture", + "shell-b", + ShellHintArm::Full, + ); assert_eq!( line_a.as_deref(), Some( @@ -2232,10 +2306,14 @@ mod tests { "the second adapter must not be silenced by the first — that is the qualified key" ); // Each is still once-per-session in its own right. - assert!( - select_and_mark_shell_hint(&a, "sess-1", "capture again", "shell-a", ShellHintArm::Full) - .is_none() - ); + assert!(select_and_mark_shell_hint( + &a, + "sess-1", + "capture again", + "shell-a", + ShellHintArm::Full + ) + .is_none()); } // [unit->REQ-SHELL-HINTS] the teaser names the REAL verb and the keyword that @@ -2252,10 +2330,18 @@ mod tests { ) .unwrap(); - let teaser = - select_and_mark_shell_hint(&m, "sess-T", "take a screenshot", "pacer", ShellHintArm::Teaser) - .expect("teaser fires"); - assert!(teaser.contains("the pacer shell has a hint about \"screenshot\""), "{teaser}"); + let teaser = select_and_mark_shell_hint( + &m, + "sess-T", + "take a screenshot", + "pacer", + ShellHintArm::Teaser, + ) + .expect("teaser fires"); + assert!( + teaser.contains("the pacer shell has a hint about \"screenshot\""), + "{teaser}" + ); assert!( teaser.contains(&format!("{SHELL_HINT_VERB} pacer")), "the teaser must name the real surfacing verb: {teaser}" @@ -2265,17 +2351,26 @@ mod tests { "a teaser withholds the text — that is what makes it a teaser: {teaser}" ); // Same session, same shell, now instantiated: the full text still arrives. - let full = - select_and_mark_shell_hint(&m, "sess-T", "take a screenshot", "pacer", ShellHintArm::Full); + let full = select_and_mark_shell_hint( + &m, + "sess-T", + "take a screenshot", + "pacer", + ShellHintArm::Full, + ); assert_eq!( full.as_deref(), Some("keyword hint for SPT shell adapter pacer: \"screenshot\"-->PACER can capture a window") ); // ...but only once. - assert!( - select_and_mark_shell_hint(&m, "sess-T", "screenshot again", "pacer", ShellHintArm::Full) - .is_none() - ); + assert!(select_and_mark_shell_hint( + &m, + "sess-T", + "screenshot again", + "pacer", + ShellHintArm::Full + ) + .is_none()); } // [unit->REQ-SHELL-HINTS] the harness key spelling is UNCHANGED by this lane. @@ -2430,7 +2525,10 @@ mod tests { establish("alice", "sid-shared"); spt_store::empower::grant_session("sid-shared", "bignet").unwrap(); - assert!(seat_holds_bignet(), "baseline: the seat holds what was proved"); + assert!( + seat_holds_bignet(), + "baseline: the seat holds what was proved" + ); assert_eq!(cmd_boundary("alice", "clear", "sid-alice-2"), 0); diff --git a/crates/spt/src/api/seal.rs b/crates/spt/src/api/seal.rs index 0ca8b2d3..3aa8fbca 100644 --- a/crates/spt/src/api/seal.rs +++ b/crates/spt/src/api/seal.rs @@ -154,8 +154,10 @@ fn render_record_for(record: &SealRecord, whom: RenderFor, labels: &NodeLabels) if let Some(sig) = &record.signature_hex { lines.push(format!("signature: present ({} hex chars)", sig.len())); } - lines.join(" -") + lines.join( + " +", + ) } /// The block `verify` prints beside its own verdict ([`RenderFor::Verify`]). @@ -225,8 +227,12 @@ fn fido2_signature_arm( )); }; let payload = fido2_signing_payload(&record.content_hash, &record.minter, record.minted_at); - match verify_backend_signature(&enrollment.backend_kind, &enrollment.pubkey_hex, &payload, sig_hex) - { + match verify_backend_signature( + &enrollment.backend_kind, + &enrollment.pubkey_hex, + &payload, + sig_hex, + ) { // Checked and sound: the arm has nothing to add — the hash arm's // verdict stands. Ok(()) => None, @@ -251,7 +257,6 @@ fn fido2_signature_arm( } } - /// The token-seam refusals shared by both verbs: malformed refuses at the /// format seam BEFORE any store lookup (so a malformed token can never read /// as merely unknown), unknown refuses by name after it. @@ -372,7 +377,11 @@ pub(crate) fn verify_outcome( if let Some(outcome) = fido2_signature_arm(enrolls, record) { return outcome; } - (0, format!("SEAL_BOUND:{token}\n{}", render_record(record)), String::new()) + ( + 0, + format!("SEAL_BOUND:{token}\n{}", render_record(record)), + String::new(), + ) } /// Print one outcome triple in the api group's convention: results → stdout, @@ -391,7 +400,11 @@ fn emit(outcome: (i32, String, String)) -> i32 { /// `spt api seal describe ` — the record's fields, or a named refusal. // [impl->REQ-SEAL-DESCRIBE] pub fn cmd_seal_describe(token: &str) -> i32 { - emit(describe_outcome(&SealStore::load(), &load_node_labels(), token)) + emit(describe_outcome( + &SealStore::load(), + &load_node_labels(), + token, + )) } /// `spt api seal verify ` — content on stdin, BOUND/NOT-BOUND verdict. @@ -477,7 +490,10 @@ mod tests { #[test] fn minter_names_a_node_only_when_the_prefix_is_unambiguous() { let one = labels(&[("aa11bb22", "KITSUBITO"), ("ff00", "OTHER")]); - assert_eq!(unique_prefix_label(&one, "aa11").as_deref(), Some("KITSUBITO")); + assert_eq!( + unique_prefix_label(&one, "aa11").as_deref(), + Some("KITSUBITO") + ); assert_eq!( human_minter("home:ling@aa11", &one), "home:ling@KITSUBITO (aa11…)" @@ -528,24 +544,44 @@ mod tests { let (store, record) = seeded(); // BOUND: the only exit-0 arm. - let (code, out, err) = verify_outcome(&store, &EnrollStore::default(), &record.token, b"ship it"); + let (code, out, err) = + verify_outcome(&store, &EnrollStore::default(), &record.token, b"ship it"); assert_eq!(code, 0); - assert!(out.starts_with(&format!("SEAL_BOUND:{}", record.token)), "{out}"); + assert!( + out.starts_with(&format!("SEAL_BOUND:{}", record.token)), + "{out}" + ); assert!(err.is_empty()); // #220: the verdict's block is the NARROW one. `token` rides the // verdict line itself, and repeating these three beside their own // answer reads as a second, weaker copy of it — they belong to // `describe`. Pinned as an ABSENCE, because the old assertion here // pinned exactly the opposite and a deleted assertion pins nothing. - assert!(!out.contains("token: "), "no token field beside the verdict: {out}"); - assert!(!out.contains("content_hash: "), "no content_hash field: {out}"); - assert!(!out.contains("ceremony_kind: "), "no ceremony_kind field: {out}"); - assert!(out.contains("minter: home:ling@aa11"), "minter rides VERBATIM: {out}"); + assert!( + !out.contains("token: "), + "no token field beside the verdict: {out}" + ); + assert!( + !out.contains("content_hash: "), + "no content_hash field: {out}" + ); + assert!( + !out.contains("ceremony_kind: "), + "no ceremony_kind field: {out}" + ); + assert!( + out.contains("minter: home:ling@aa11"), + "minter rides VERBATIM: {out}" + ); // NOT-BOUND: a one-byte delta — verdict on stdout, exit nonzero. - let (code, out, _) = verify_outcome(&store, &EnrollStore::default(), &record.token, b"ship it!"); + let (code, out, _) = + verify_outcome(&store, &EnrollStore::default(), &record.token, b"ship it!"); assert_eq!(code, 1); - assert!(out.starts_with(&format!("SEAL_NOT_BOUND:{}", record.token)), "{out}"); + assert!( + out.starts_with(&format!("SEAL_NOT_BOUND:{}", record.token)), + "{out}" + ); assert!( out.contains(&record.content_hash), "expected-vs-presented hashes in the verdict" @@ -582,15 +618,25 @@ mod tests { assert_eq!(verify(b"ship it"), 0, "the exact bytes"); assert_eq!(verify(b"ship it\n"), 0, "echo's trailing newline"); assert_eq!(verify(b"ship it\r\n"), 0, "a Windows shell's CRLF"); - assert_eq!(verify(b" ship it "), 0, "both ends, mirroring mint's trim"); + assert_eq!( + verify(b" ship it "), + 0, + "both ends, mirroring mint's trim" + ); assert_eq!(verify(b"ship it!"), 1, "a real one-byte delta is untouched"); assert_eq!(verify(b"shipit"), 1, "interior whitespace is CONTENT"); // A seal minted OVER trailing whitespace still binds its exact bytes: // the fallback never replaces the exact hash, it only follows it. let mut spaced_store = SealStore::default(); - let spaced = - mint_seal(&mut spaced_store, b"ship it\n", "home:ling@aa11", "test", 42).unwrap(); + let spaced = mint_seal( + &mut spaced_store, + b"ship it\n", + "home:ling@aa11", + "test", + 42, + ) + .unwrap(); let (code, _, _) = verify_outcome( &spaced_store, &EnrollStore::default(), @@ -629,7 +675,12 @@ mod tests { // the seeded record uses) with the test pubkey. let mut enrolls = EnrollStore::default(); spt_store::enroll::mint_enrollment( - &mut enrolls, &blob_hex, "aa11bb22", "home", "hello-kcm-rs256", 1, + &mut enrolls, + &blob_hex, + "aa11bb22", + "home", + "hello-kcm-rs256", + 1, ) .unwrap(); @@ -648,8 +699,9 @@ mod tests { .iter() .map(|b| format!("{b:02x}")) .collect(); - let rec = spt_store::seal::mint_seal_fido2(&mut store, content, minter, minted_at, &sig_hex) - .unwrap(); + let rec = + spt_store::seal::mint_seal_fido2(&mut store, content, minter, minted_at, &sig_hex) + .unwrap(); (store, enrolls, rec.token) } @@ -674,17 +726,21 @@ mod tests { verify_outcome(&store, &EnrollStore::default(), &token, b"ship it signed"); assert_eq!(code, 1); assert!(out.is_empty(), "{out}"); - assert!(err.starts_with(&format!("SEAL_VERIFY_NO_ENROLLMENT:{token}")), "{err}"); + assert!( + err.starts_with(&format!("SEAL_VERIFY_NO_ENROLLMENT:{token}")), + "{err}" + ); // Unknown backend kind in the enrollment: its own named refusal. let mut weird = EnrollStore::default(); - spt_store::enroll::mint_enrollment( - &mut weird, "aabb", "aa11bb22", "home", "quantum-x1", 1, - ) - .unwrap(); + spt_store::enroll::mint_enrollment(&mut weird, "aabb", "aa11bb22", "home", "quantum-x1", 1) + .unwrap(); let (code, _, err) = verify_outcome(&store, &weird, &token, b"ship it signed"); assert_eq!(code, 1); - assert!(err.starts_with(&format!("SEAL_VERIFY_UNKNOWN_BACKEND:{token}")), "{err}"); + assert!( + err.starts_with(&format!("SEAL_VERIFY_UNKNOWN_BACKEND:{token}")), + "{err}" + ); // A tampered record (signature stripped) is NOT-BOUND: a fido2 mint // that cannot be checked is not evidence. @@ -722,6 +778,9 @@ mod tests { assert!(out.contains("ceremony_kind: fido2"), "{out}"); assert!(out.contains("signature: present ("), "{out}"); let sig_hex = store.find(&token).unwrap().signature_hex.clone().unwrap(); - assert!(!out.contains(&sig_hex), "raw signature hex never renders: {out}"); + assert!( + !out.contains(&sig_hex), + "raw signature hex never renders: {out}" + ); } } diff --git a/crates/spt/src/api/startup.rs b/crates/spt/src/api/startup.rs index 2e615314..790fdb6e 100644 --- a/crates/spt/src/api/startup.rs +++ b/crates/spt/src/api/startup.rs @@ -312,9 +312,18 @@ fn conflict_lines(id: &str, held: &str, owner_unverified: bool) -> Vec { // [impl->REQ-HAZARD-BIND-CONFLICT-PID-ABA] fn conflict_verdict(custody: RelayLiveness, pid_alive: impl FnOnce() -> bool) -> ConflictVerdict { match custody { - RelayLiveness::Held => ConflictVerdict { holds: true, unverified: false }, - RelayLiveness::Gone => ConflictVerdict { holds: false, unverified: false }, - RelayLiveness::Unproven => ConflictVerdict { holds: pid_alive(), unverified: true }, + RelayLiveness::Held => ConflictVerdict { + holds: true, + unverified: false, + }, + RelayLiveness::Gone => ConflictVerdict { + holds: false, + unverified: false, + }, + RelayLiveness::Unproven => ConflictVerdict { + holds: pid_alive(), + unverified: true, + }, } } @@ -609,14 +618,11 @@ fn establish_perch( info::PidValue::Numeric(n) => Some(n), info::PidValue::Busy(_) => None, }; - let custody = - spt_store::liveness::relay_liveness(owner_pid, existing.pid_started_at); - let verdict = conflict_verdict(custody, || { - owner_pid.is_some_and(proc::is_process_alive) - }); + let custody = spt_store::liveness::relay_liveness(owner_pid, existing.pid_started_at); + let verdict = + conflict_verdict(custody, || owner_pid.is_some_and(proc::is_process_alive)); let owner_alive = verdict.holds; - if owner_alive && !existing.session_id.is_empty() && existing.session_id != session_id - { + if owner_alive && !existing.session_id.is_empty() && existing.session_id != session_id { return Err(BindError::Conflict { id: id.to_string(), held: existing.session_id.clone(), @@ -723,9 +729,7 @@ fn establish_perch( // [impl->REQ-DIGEST-PROFILE-ENV] rec.read_env = resolve_read_env( adapter - .and_then(|a| { - spt_runtime::registry::resolve_option(&perch::adapters_dir(), a).ok() - }) + .and_then(|a| spt_runtime::registry::resolve_option(&perch::adapters_dir(), a).ok()) .map(|(_, m)| { spt_runtime::runtime::capture_read_env(&m, |k| std::env::var(k).ok()) }), @@ -921,9 +925,10 @@ pub fn cmd_listen( // gate, so a first-mover listen would be the reserved-id bypass wearing a // different verb. // [impl->REQ-ER-RESERVED-ID-SPAWN-REFUSAL] - if let Some(refusal) = - crate::api::engineroom::reserved_bind_refusal(id, crate::api::engineroom::engine_room_hosted()) - { + if let Some(refusal) = crate::api::engineroom::reserved_bind_refusal( + id, + crate::api::engineroom::engine_room_hosted, + ) { spt_proto::emit_line_err!("RESERVED_ID:{id}: {refusal}"); return EXIT_REFUSED; } @@ -979,7 +984,9 @@ pub fn cmd_listen( let sid = session_id.expect("guarded by the match arm"); match bind_from_session_id(id, sid, parent_pid, subnet, adapter_option.as_deref()) { Ok(t) => { - spt_proto::emit_line_err!("SID_BIND:{id}: no live seed — bound from --session-id"); + spt_proto::emit_line_err!( + "SID_BIND:{id}: no live seed — bound from --session-id" + ); t } Err(e) => { @@ -1107,9 +1114,10 @@ pub fn cmd_bind( // engine room's own harness binds its own perch through this verb, so the // rule is not-as-a-first-mover rather than never. // [impl->REQ-ER-RESERVED-ID-SPAWN-REFUSAL] - if let Some(refusal) = - crate::api::engineroom::reserved_bind_refusal(id, crate::api::engineroom::engine_room_hosted()) - { + if let Some(refusal) = crate::api::engineroom::reserved_bind_refusal( + id, + crate::api::engineroom::engine_room_hosted, + ) { spt_proto::emit_line_err!("RESERVED_ID:{id}: {refusal}"); return EXIT_REFUSED; } @@ -1209,9 +1217,15 @@ pub fn cmd_bind( fn report_bind_error(e: &BindError) { match e { - BindError::NoSeed(p) => spt_proto::emit_line_err!("NO_SEED:{p} (no seed for this parent pid)"), - BindError::StaleSeed(p) => spt_proto::emit_line_err!("STALE_SEED:{p} (anchor process is dead)"), - BindError::EmptySession => spt_proto::emit_line_err!("EMPTY_SESSION: seed carried no session id"), + BindError::NoSeed(p) => { + spt_proto::emit_line_err!("NO_SEED:{p} (no seed for this parent pid)") + } + BindError::StaleSeed(p) => { + spt_proto::emit_line_err!("STALE_SEED:{p} (anchor process is dead)") + } + BindError::EmptySession => { + spt_proto::emit_line_err!("EMPTY_SESSION: seed carried no session id") + } BindError::Conflict { id, held, @@ -1483,7 +1497,14 @@ mod tests { // 1. BIND — the spt-hosted bind EARNS the hosting authority. assert_eq!( - cmd_bind("topo", Some("sid-topo".into()), None, None, None, "live_agent"), + cmd_bind( + "topo", + Some("sid-topo".into()), + None, + None, + None, + "live_agent" + ), 0, "the spt-hosted bind succeeds" ); @@ -1518,7 +1539,9 @@ mod tests { // stamps on the sessions poll (driven here, as a brain would). let mut driver = connect_broker(&sock); driver.attach(session, 0).expect("attach as controller"); - let _ = driver.sessions().expect("sessions poll converges the stamps"); + let _ = driver + .sessions() + .expect("sessions poll converges the stamps"); let controlled = info::read_info(&perch).unwrap(); assert!( controlled.controlled, @@ -1615,7 +1638,14 @@ mod tests { }) .expect("spawn the endpoint's PTY session"); assert_eq!( - cmd_bind("deadpty", Some("sid-dead".into()), None, None, None, "live_agent"), + cmd_bind( + "deadpty", + Some("sid-dead".into()), + None, + None, + None, + "live_agent" + ), 0 ); let perch = perch::resolve_perch_path("deadpty", ParentHint::Infer); @@ -1750,7 +1780,9 @@ mod tests { let mut child = { #[cfg(windows)] { - std::process::Command::new("cmd").args(["/C", "rem"]).spawn() + std::process::Command::new("cmd") + .args(["/C", "rem"]) + .spawn() } #[cfg(unix)] { @@ -1761,7 +1793,7 @@ mod tests { let pid = child.id(); child.wait().expect("reap probe child"); drop(child); // close our process handle — on Windows a held handle keeps the pid probe-able - // Poll to the parent-watch cadence: the pid must read gone within one window. + // Poll to the parent-watch cadence: the pid must read gone within one window. let gone = { let mut g = false; for _ in 0..40 { @@ -1875,7 +1907,10 @@ mod tests { let eof = Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"); let msg = seed_fail_message(4321, &eof); assert!(msg.starts_with("SEED_FAIL:4321:")); - assert!(msg.contains("stale pre-0.9.0 broker"), "names the cause: {msg}"); + assert!( + msg.contains("stale pre-0.9.0 broker"), + "names the cause: {msg}" + ); assert!(msg.contains("spt daemon stop"), "names the fix: {msg}"); assert!( !msg.contains("failed to fill whole buffer"), @@ -1935,7 +1970,9 @@ mod tests { let anchor = std::process::id(); let mut subnets = spt_store::subnet::SubnetStore::load(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); put_seed(®, anchor, "sid-1"); @@ -1969,7 +2006,9 @@ mod tests { ); // Multi-subnet node: a NEW endpoint refuses without an explicit pick. - subnets.create_subnet("work", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("work", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); put_seed(®, anchor, "sid-9"); let err = bind_from_seed("fresh", anchor, None, None).unwrap_err(); @@ -2061,12 +2100,24 @@ mod tests { #[test] fn listen_online_gate_refuses_capability_only_online() { // The full table: capability alone never suffices. - assert!(!listen_online_gate(true, Some("ready_agent")), "the hybrid birth shape"); - assert!(!listen_online_gate(true, None), "no persisted record — nothing earned"); + assert!( + !listen_online_gate(true, Some("ready_agent")), + "the hybrid birth shape" + ); + assert!( + !listen_online_gate(true, None), + "no persisted record — nothing earned" + ); assert!(!listen_online_gate(true, Some("gateway"))); - assert!(!listen_online_gate(false, Some("live_agent")), "not live-capable — no stamp"); + assert!( + !listen_online_gate(false, Some("live_agent")), + "not live-capable — no stamp" + ); assert!(!listen_online_gate(false, None)); - assert!(listen_online_gate(true, Some("live_agent")), "the one earned shape"); + assert!( + listen_online_gate(true, Some("live_agent")), + "the one earned shape" + ); } // W3 (REQ-HAZARD-BIND-CWD-UNSET): the refuted v0.12.1 P1 — a freshly bound @@ -2083,19 +2134,37 @@ mod tests { #[test] fn bind_records_cwd_so_picker_can_group_by_project() { let _h = isolated_home(); - let code = cmd_bind("cwdy", Some("sid-cwd".into()), None, None, None, "live_agent"); + let code = cmd_bind( + "cwdy", + Some("sid-cwd".into()), + None, + None, + None, + "live_agent", + ); assert_eq!(code, 0); let rec = info::read_info(&perch::resolve_perch_path("cwdy", ParentHint::Infer)).unwrap(); - let cwd = rec.cwd.expect("bind must record info.cwd (was never set — the refuted P1)"); + let cwd = rec + .cwd + .expect("bind must record info.cwd (was never set — the refuted P1)"); assert!(!cwd.is_empty(), "recorded cwd must be non-empty"); // It is THIS process's current_dir (what cmd_bind passes via current_dir()). - let expected = std::env::current_dir().unwrap().to_string_lossy().into_owned(); - assert_eq!(cwd, expected, "bind records its own current_dir as the perch cwd"); + let expected = std::env::current_dir() + .unwrap() + .to_string_lossy() + .into_owned(); + assert_eq!( + cwd, expected, + "bind records its own current_dir as the perch cwd" + ); // The picker derives project membership off exactly this field // (data.rs:138 → project_id_for_dir); the derivation is non-empty so the // endpoint resolves to a real project category, not "" (no membership). let project = spt_store::project::project_id_for_dir(std::path::Path::new(&cwd)); - assert!(!project.is_empty(), "cwd-derived project id is non-empty: {project:?}"); + assert!( + !project.is_empty(), + "cwd-derived project id is non-empty: {project:?}" + ); } // [unit->REQ-HAZARD-BIND-CWD-UNSET] CARRY-FORWARD: a revive that supplies no @@ -2111,10 +2180,20 @@ mod tests { let anchor = std::process::id(); // First bind: spt-hosted, stamps a concrete cwd (this process's dir). - let code = cmd_bind("revivee", Some("sid-1".into()), None, None, None, "live_agent"); + let code = cmd_bind( + "revivee", + Some("sid-1".into()), + None, + None, + None, + "live_agent", + ); assert_eq!(code, 0); let perch_path = perch::resolve_perch_path("revivee", ParentHint::Infer); - let first = info::read_info(&perch_path).unwrap().cwd.expect("first bind set cwd"); + let first = info::read_info(&perch_path) + .unwrap() + .cwd + .expect("first bind set cwd"); assert!(!first.is_empty()); // Re-bind via the harness-hosted seed path with seed.cwd = None (put_seed @@ -2143,7 +2222,14 @@ mod tests { // First bind, then the daemon stamps a DORMANT resting intent + its // auto-suspend anchor (info::set_rest_state — the D9-2 / REQ-INST-3 write). - let code = cmd_bind("resty", Some("sid-1".into()), None, None, None, "live_agent"); + let code = cmd_bind( + "resty", + Some("sid-1".into()), + None, + None, + None, + "live_agent", + ); assert_eq!(code, 0); let perch_path = perch::resolve_perch_path("resty", ParentHint::Infer); info::set_rest_state(&perch_path, "dormant", Some(1_700_000_000_000)) @@ -2224,10 +2310,21 @@ mod tests { assert_eq!(stopped.rest_state.as_deref(), Some("suspended")); // a fresh `endpoint start` binds the fresh life under a NEW session id. - let code = cmd_bind("recreated", Some("sid-2".into()), None, None, None, "live_agent"); + let code = cmd_bind( + "recreated", + Some("sid-2".into()), + None, + None, + None, + "live_agent", + ); assert_eq!(code, 0); let after = info::read_info(&perch_path).unwrap(); - assert_eq!(after.status.as_deref(), Some("online"), "the fresh bind is online"); + assert_eq!( + after.status.as_deref(), + Some("online"), + "the fresh bind is online" + ); assert_eq!( after.rest_state.as_deref(), Some("active"), @@ -2248,7 +2345,14 @@ mod tests { let _h = isolated_home(); let _reg = start_seed_daemon(); - let code = cmd_bind("virgin", Some("sid-1".into()), None, None, None, "live_agent"); + let code = cmd_bind( + "virgin", + Some("sid-1".into()), + None, + None, + None, + "live_agent", + ); assert_eq!(code, 0); let rec = info::read_info(&perch::resolve_perch_path("virgin", ParentHint::Infer)).unwrap(); assert_eq!( @@ -2287,11 +2391,9 @@ mod tests { /// background — so `engine_room_hosted()` is answered by a REAL broker whose /// session table this test controls. fn rig_broker_at_the_real_socket(dir: &std::path::Path) -> Arc { - let broker = spt_daemon::Broker::bind_in( - &spt_daemon::broker_socket_name(), - dir.join("effects.log"), - ) - .expect("bind the rig broker at the production socket name"); + let broker = + spt_daemon::Broker::bind_in(&spt_daemon::broker_socket_name(), dir.join("effects.log")) + .expect("bind the rig broker at the production socket name"); let serve = Arc::clone(&broker); std::thread::spawn(move || { let _ = serve.serve(); @@ -2358,11 +2460,20 @@ mod tests { // ROW 2 — the SAME seam, an ordinary id: untouched. assert_eq!( - cmd_bind("todlando", Some("sid-ord".into()), None, None, None, "live_agent"), + cmd_bind( + "todlando", + Some("sid-ord".into()), + None, + None, + None, + "live_agent" + ), 0, "an ordinary id binds exactly as before" ); - assert!(info::read_info(&perch::resolve_perch_path("todlando", ParentHint::Infer)).is_some()); + assert!( + info::read_info(&perch::resolve_perch_path("todlando", ParentHint::Infer)).is_some() + ); // ROW 3 — the COMPLETION: the broker now hosts the engine room's // session, which only its bring-up could have created. The same call @@ -2374,7 +2485,9 @@ mod tests { "the engine room's own harness binds its own perch" ); assert_eq!( - info::read_info(&er_perch).expect("the completion bind established the perch").session_id, + info::read_info(&er_perch) + .expect("the completion bind established the perch") + .session_id, "sid-er" ); } @@ -2406,7 +2519,15 @@ version = \"1\" // ROW 1 — FIRST MOVER: refused, nothing minted. assert_ne!( - cmd_listen(er, Some(std::process::id()), true, Some("mock"), Some(&manifest), None, Some("sid-er")), + cmd_listen( + er, + Some(std::process::id()), + true, + Some("mock"), + Some(&manifest), + None, + Some("sid-er") + ), 0, "a listener cannot mint the reserved identity" ); @@ -2417,7 +2538,15 @@ version = \"1\" // ROW 2 — an ordinary id through the identical call: unaffected. assert_eq!( - cmd_listen("todlando", Some(std::process::id()), true, Some("mock"), Some(&manifest), None, Some("sid-ord")), + cmd_listen( + "todlando", + Some(std::process::id()), + true, + Some("mock"), + Some(&manifest), + None, + Some("sid-ord") + ), 0, "an ordinary id listens exactly as before" ); @@ -2425,7 +2554,15 @@ version = \"1\" // ROW 3 — the COMPLETION: the broker hosts the engine room's session. let _spawner = host_a_session_for(er); assert_eq!( - cmd_listen(er, Some(std::process::id()), true, Some("mock"), Some(&manifest), None, Some("sid-er")), + cmd_listen( + er, + Some(std::process::id()), + true, + Some("mock"), + Some(&manifest), + None, + Some("sid-er") + ), 0, "the engine room's own harness completes its bring-up here" ); @@ -2438,7 +2575,14 @@ version = \"1\" #[test] // [unit->REQ-SEAM-POSTSPAWN] first-contact bind establishes a live perch. fn post_spawn_bind_establishes_perch() { let _h = isolated_home(); - let code = cmd_bind("bob", Some("sid-boot".into()), None, None, None, "live_agent"); + let code = cmd_bind( + "bob", + Some("sid-boot".into()), + None, + None, + None, + "live_agent", + ); assert_eq!(code, 0); let rec = info::read_info(&perch::resolve_perch_path("bob", ParentHint::Infer)).unwrap(); assert_eq!(rec.session_id, "sid-boot"); @@ -2449,11 +2593,25 @@ version = \"1\" fn rebind_same_session_ok() { let _h = isolated_home(); assert_eq!( - cmd_bind("bob", Some("sid-boot".into()), None, None, None, "live_agent"), + cmd_bind( + "bob", + Some("sid-boot".into()), + None, + None, + None, + "live_agent" + ), 0 ); assert_eq!( - cmd_bind("bob", Some("sid-boot".into()), None, None, None, "live_agent"), + cmd_bind( + "bob", + Some("sid-boot".into()), + None, + None, + None, + "live_agent" + ), 0 ); } @@ -2466,7 +2624,14 @@ version = \"1\" fn bind_with_type_establishes_a_gateway_endpoint() { let _h = isolated_home(); assert_eq!( - cmd_bind("playdate-gw", Some("sid-gw".into()), None, None, None, "gateway"), + cmd_bind( + "playdate-gw", + Some("sid-gw".into()), + None, + None, + None, + "gateway" + ), 0 ); let perch = perch::resolve_perch_path("playdate-gw", ParentHint::Infer); @@ -2474,14 +2639,20 @@ version = \"1\" // The open-type tag round-trips to the user-backed Gateway recognizer // the user-msg identity gate keys on (REQ-MSG-5). - let ty = spt_proto::endpoint::EndpointType::from_tag( - &info::read_info(&perch).unwrap().state, - ); + let ty = + spt_proto::endpoint::EndpointType::from_tag(&info::read_info(&perch).unwrap().state); assert!(spt_proto::event::is_gateway_endpoint(&ty)); // Revive without --type (default live_agent) preserves the gateway type. assert_eq!( - cmd_bind("playdate-gw", Some("sid-gw".into()), None, None, None, "live_agent"), + cmd_bind( + "playdate-gw", + Some("sid-gw".into()), + None, + None, + None, + "live_agent" + ), 0 ); assert_eq!(info::read_info(&perch).unwrap().state, "gateway"); @@ -2507,17 +2678,28 @@ version = \"1\" // gateway carry-forward test's same-sid revive). let perch = perch::resolve_perch_path("hybrid", ParentHint::Infer); std::fs::create_dir_all(&perch).unwrap(); - let prior = info::InfoJson::new("hybrid", "0", std::process::id(), "sid-bind", "ready_agent"); + let prior = + info::InfoJson::new("hybrid", "0", std::process::id(), "sid-bind", "ready_agent"); info::write_info(&perch, &prior).unwrap(); // spt-hosted live_agent bind over it (same session — a revive). assert_eq!( - cmd_bind("hybrid", Some("sid-bind".into()), None, None, None, "live_agent"), + cmd_bind( + "hybrid", + Some("sid-bind".into()), + None, + None, + None, + "live_agent" + ), 0 ); let after = info::read_info(&perch).unwrap(); - assert_eq!(after.state, "ready_agent", "the prior type is PRESERVED (REQ-EP-6)"); + assert_eq!( + after.state, "ready_agent", + "the prior type is PRESERVED (REQ-EP-6)" + ); assert_eq!( after.controllable, Some(true), @@ -2544,7 +2726,10 @@ version = \"1\" ); let perch = perch::resolve_perch_path("gwoff", ParentHint::Infer); let after = info::read_info(&perch).unwrap(); - assert_eq!(after.controllable, None, "a gateway bind is not broker-PTY-controllable"); + assert_eq!( + after.controllable, None, + "a gateway bind is not broker-PTY-controllable" + ); assert_ne!( after.status.as_deref(), Some(spt_store::liveness::STATUS_ONLINE), @@ -2996,7 +3181,10 @@ version = \"1\" let rec = info::read_info(&perch::resolve_perch_path("late", ParentHint::Infer)) .expect("perch info.json after sid-fallback bind"); - assert_eq!(rec.session_id, "sid-late", "the perch records the supplied sid"); + assert_eq!( + rec.session_id, "sid-late", + "the perch records the supplied sid" + ); assert_eq!(rec.state, "live_agent"); assert_eq!(rec.parent_pid, Some(anchor)); assert!(perch::resolve_ready_file("late", ParentHint::Infer).exists()); @@ -3041,8 +3229,14 @@ version = \"1\" #[test] fn seed_restorable_spends_dead_seeds_restores_recoverable() { // SPENT: a dead-anchor or contentless seed can never bind as itself. - assert!(!seed_restorable(&BindError::StaleSeed(1)), "dead anchor is spent"); - assert!(!seed_restorable(&BindError::EmptySession), "empty session is spent"); + assert!( + !seed_restorable(&BindError::StaleSeed(1)), + "dead anchor is spent" + ); + assert!( + !seed_restorable(&BindError::EmptySession), + "empty session is spent" + ); // RESTORED: the anchor is alive; the corrected retry must find its seed again. assert!( seed_restorable(&BindError::Conflict { @@ -3145,8 +3339,8 @@ version = \"1\" // An alive parent pid clears the liveness gate, so the bind reaches the // establish-time custody guard — which refuses the bearer-string squat. - let err = bind_from_session_id("attacker", "psid-x", std::process::id(), None, None) - .unwrap_err(); + let err = + bind_from_session_id("attacker", "psid-x", std::process::id(), None, None).unwrap_err(); assert_eq!( err, BindError::PsycheCustodySquat { diff --git a/crates/spt/src/api/worker.rs b/crates/spt/src/api/worker.rs index 185730f9..902b6107 100644 --- a/crates/spt/src/api/worker.rs +++ b/crates/spt/src/api/worker.rs @@ -256,8 +256,12 @@ mod tests { &InfoJson::new("alice", "0", std::process::id(), "", "ready_agent"), ) .unwrap(); - assert_eq!(cmd_worker_start("alice", None, None, Some("presented-sid")), 0); - let rec = info::read_info(&perch::resolve_perch_path("alice-w1", ParentHint::Infer)).unwrap(); + assert_eq!( + cmd_worker_start("alice", None, None, Some("presented-sid")), + 0 + ); + let rec = + info::read_info(&perch::resolve_perch_path("alice-w1", ParentHint::Infer)).unwrap(); assert_eq!( rec.session_id, "presented-sid", "empty parent sid → fall back to the presented sid" diff --git a/crates/spt/src/authseam.rs b/crates/spt/src/authseam.rs index 388b5044..0fe4de1e 100644 --- a/crates/spt/src/authseam.rs +++ b/crates/spt/src/authseam.rs @@ -118,7 +118,10 @@ mod hello { /// /// `what` names the operation so one vocabulary serves all three seam /// questions without a per-call-site copy of the sentences. - pub(super) fn refusal_for_status(status: KeyCredentialStatus, what: &str) -> Result<(), String> { + pub(super) fn refusal_for_status( + status: KeyCredentialStatus, + what: &str, + ) -> Result<(), String> { match status { KeyCredentialStatus::Success => Ok(()), KeyCredentialStatus::NotFound => Err(unavailable(&format!( @@ -168,14 +171,19 @@ mod hello { /// completion handler itself and waits on a channel. `SetCompleted` fires /// immediately when the operation has already finished, so there is no race /// between registering and completing. - fn block_on(op: &IAsyncOperation, what: &str) -> Result { + fn block_on( + op: &IAsyncOperation, + what: &str, + ) -> Result { let (tx, rx) = std::sync::mpsc::channel::<()>(); - op.SetCompleted(&AsyncOperationCompletedHandler::::new(move |_op, _status| { - // A send error means the waiter is already gone; the result is - // collected by whoever still holds the operation. - let _ = tx.send(()); - Ok(()) - })) + op.SetCompleted(&AsyncOperationCompletedHandler::::new( + move |_op, _status| { + // A send error means the waiter is already gone; the result is + // collected by whoever still holds the operation. + let _ = tx.send(()); + Ok(()) + }, + )) .map_err(|e| call_failed(what, e))?; rx.recv().map_err(|_| { unavailable(&format!( diff --git a/crates/spt/src/cli.rs b/crates/spt/src/cli.rs index 2e9fe594..d812b57b 100644 --- a/crates/spt/src/cli.rs +++ b/crates/spt/src/cli.rs @@ -1100,7 +1100,11 @@ enum AccessCmd { #[arg(long = "endpoint", value_name = "ID", conflicts_with = "node")] subject_endpoint: Option, /// Subject: an origin node — its pubkey hex, `self` for this node, or a node name. - #[arg(long = "node", value_name = "NODE", conflicts_with = "subject_endpoint")] + #[arg( + long = "node", + value_name = "NODE", + conflicts_with = "subject_endpoint" + )] subject_node: Option, /// Subject: any member of this subnet. #[arg( @@ -1129,7 +1133,11 @@ enum AccessCmd { #[arg(long = "endpoint", value_name = "ID")] subject_endpoint: Option, /// Subject: an origin node — its pubkey hex, `self` for this node, or a node name. - #[arg(long = "node", value_name = "NODE", conflicts_with = "subject_endpoint")] + #[arg( + long = "node", + value_name = "NODE", + conflicts_with = "subject_endpoint" + )] subject_node: Option, /// Subject: any member of this subnet. #[arg( @@ -1159,7 +1167,11 @@ enum AccessCmd { #[arg(long = "endpoint", value_name = "ID")] subject_endpoint: Option, /// Subject: an origin node — its pubkey hex, `self` for this node, or a node name. - #[arg(long = "node", value_name = "NODE", conflicts_with = "subject_endpoint")] + #[arg( + long = "node", + value_name = "NODE", + conflicts_with = "subject_endpoint" + )] subject_node: Option, /// Subject: any member of this subnet. #[arg( @@ -1318,7 +1330,11 @@ enum DaemonAccessCmd { #[arg(long = "endpoint", value_name = "ID")] subject_endpoint: Option, /// Subject: an origin node — its pubkey hex, `self` for this node, or a node name. - #[arg(long = "node", value_name = "NODE", conflicts_with = "subject_endpoint")] + #[arg( + long = "node", + value_name = "NODE", + conflicts_with = "subject_endpoint" + )] subject_node: Option, #[arg( long = "any-of", @@ -1338,7 +1354,11 @@ enum DaemonAccessCmd { #[arg(long = "endpoint", value_name = "ID")] subject_endpoint: Option, /// Subject: an origin node — its pubkey hex, `self` for this node, or a node name. - #[arg(long = "node", value_name = "NODE", conflicts_with = "subject_endpoint")] + #[arg( + long = "node", + value_name = "NODE", + conflicts_with = "subject_endpoint" + )] subject_node: Option, #[arg( long = "any-of", @@ -1358,7 +1378,11 @@ enum DaemonAccessCmd { #[arg(long = "endpoint", value_name = "ID")] subject_endpoint: Option, /// Subject: an origin node — its pubkey hex, `self` for this node, or a node name. - #[arg(long = "node", value_name = "NODE", conflicts_with = "subject_endpoint")] + #[arg( + long = "node", + value_name = "NODE", + conflicts_with = "subject_endpoint" + )] subject_node: Option, #[arg( long = "any-of", @@ -1456,10 +1480,7 @@ enum AdapterCmd { }, /// Delete a **local** profile. Refuses a shipped profile name (adapter-owned, /// immutable) and errors if no local file exists. - DeleteProfile { - adapter: String, - name: String, - }, + DeleteProfile { adapter: String, name: String }, /// Read a `[strings]` dot-path from an adapter option's merged view /// (`[:profile] `). Resolves through the profile overlay /// like every other consumer; prints the value (strings raw, else JSON). @@ -2008,7 +2029,10 @@ fn decide_bare(stdin_tty: bool, stdout_tty: bool) -> BareAction { fn bare_invocation(template: String) -> i32 { use clap::CommandFactory; use std::io::IsTerminal; - match decide_bare(std::io::stdin().is_terminal(), std::io::stdout().is_terminal()) { + match decide_bare( + std::io::stdin().is_terminal(), + std::io::stdout().is_terminal(), + ) { BareAction::Picker => crate::picker::run(None, None), BareAction::Help => { // Render the help, then transform its inline Markdown to terminal @@ -2016,7 +2040,10 @@ fn bare_invocation(template: String) -> i32 { // would emit the raw `**`/backtick markers verbatim. let cmd = Cli::command(); let raw = cmd.help_template(template).render_help().to_string(); - print!("{}", crate::helpfmt::render(&raw, crate::helpfmt::stdout_color())); + print!( + "{}", + crate::helpfmt::render(&raw, crate::helpfmt::stdout_color()) + ); println!(); 0 } @@ -2309,7 +2336,9 @@ pub fn run() -> i32 { // Bare `spt subnet` = the flagless status view WITH the hint // footer; explicit `status` drops it (M8 decision 12). None => cmd_subnet_status(None, false, true, json), - Some(SubnetCmd::Status { name, nodes }) => cmd_subnet_status(name, nodes, false, json), + Some(SubnetCmd::Status { name, nodes }) => { + cmd_subnet_status(name, nodes, false, json) + } Some(SubnetCmd::Create { name, open, closed }) => { cmd_subnet_create(name, open, closed) } @@ -2413,7 +2442,12 @@ pub fn run() -> i32 { EndpointCmd::Resume { id } => cmd_endpoint_resume(&id), EndpointCmd::AutoStart { id, off } => cmd_endpoint_auto_start(&id, off), }, - Cmd::Rc { id, view, take, code } => cmd_rc(&id, rc_intent(view, take), code), + Cmd::Rc { + id, + view, + take, + code, + } => cmd_rc(&id, rc_intent(view, take), code), // [impl->REQ-USHER-LIFECYCLE-VERBS] Cmd::Go { id } => cmd_go(&id), Cmd::Grant { action } => cmd_grant(action, json), @@ -2468,8 +2502,14 @@ pub fn run() -> i32 { for_endpoint, send_only, send_receive, - } => match knock_route_bare(action, target, surfaces, for_endpoint, send_only, send_receive) - { + } => match knock_route_bare( + action, + target, + surfaces, + for_endpoint, + send_only, + send_receive, + ) { Ok(action) => cmd_knock(action), Err(msg) => { eprintln!("{msg}"); @@ -2530,8 +2570,12 @@ fn cmd_spool_audit(id: &str, json: bool) -> i32 { "taken by {} sid={} pid={} at={}", r.taken_leg.as_deref().unwrap_or("?"), r.taken_sid.as_deref().unwrap_or("-"), - r.taken_pid.map(|p| p.to_string()).unwrap_or_else(|| "-".to_string()), - r.taken_at_ms.map(|m| m.to_string()).unwrap_or_else(|| "-".to_string()), + r.taken_pid + .map(|p| p.to_string()) + .unwrap_or_else(|| "-".to_string()), + r.taken_at_ms + .map(|m| m.to_string()) + .unwrap_or_else(|| "-".to_string()), ) } else { "pending".to_string() @@ -2641,7 +2685,9 @@ fn cmd_digest(id: &str, follow: bool, json: bool, last: Option, after: Op 0 } Ok(None) => { - spt_proto::emit_line_err!("NO_DIGEST:{id} has no activity buffer (no session-log source / no records yet?)"); + spt_proto::emit_line_err!( + "NO_DIGEST:{id} has no activity buffer (no session-log source / no records yet?)" + ); 1 } Err(e) => { @@ -2703,7 +2749,9 @@ fn cmd_digest_remote(id: &str, json: bool, last: Option, after: Option { - spt_proto::emit_line_err!("NO_ROUTE:{id} — no visible instance of that endpoint on another node"); + spt_proto::emit_line_err!( + "NO_ROUTE:{id} — no visible instance of that endpoint on another node" + ); 1 } O::NoReply { node } => { @@ -2739,10 +2787,12 @@ fn filter_after(digest: &spt_term::Digest, cursor: u64) -> (spt_term::Digest, bo .turns .iter() .flat_map(|t| { - t.input_seq.into_iter().chain(t.entries.iter().filter_map(|e| match e { - DigestEntry::Agent { seq, .. } | DigestEntry::ToolSprint { seq, .. } => *seq, - _ => None, - })) + t.input_seq + .into_iter() + .chain(t.entries.iter().filter_map(|e| match e { + DigestEntry::Agent { seq, .. } | DigestEntry::ToolSprint { seq, .. } => *seq, + _ => None, + })) }) .min(); if let Some(floor) = lowest { @@ -2775,7 +2825,8 @@ fn filter_after(digest: &spt_term::Digest, cursor: u64) -> (spt_term::Digest, bo let has_new_activity = entries.iter().any(|e| { matches!( e, - DigestEntry::Agent { seq: Some(_), .. } | DigestEntry::ToolSprint { seq: Some(_), .. } + DigestEntry::Agent { seq: Some(_), .. } + | DigestEntry::ToolSprint { seq: Some(_), .. } ) }); if input_new || has_new_activity { @@ -2825,8 +2876,8 @@ fn digest_snapshot_output( ); } } - let out = serde_json::to_string_pretty(&v) - .unwrap_or_else(|_| spt_daemon::digest_to_json(digest)); + let out = + serde_json::to_string_pretty(&v).unwrap_or_else(|_| spt_daemon::digest_to_json(digest)); (out, Vec::new()) } else { let mut err = Vec::new(); @@ -3042,8 +3093,16 @@ mod reserved_id_tests { fn endpoint_run_refuses_the_reserved_id_and_saves_nothing() { let _home = spt_test_support::TestHome::new(); let reserved = spt_store::engineroom::ENGINE_ROOM_ID; - let code = - super::cmd_endpoint_run("claude-spt", reserved, None, None, false, false, false, None); + let code = super::cmd_endpoint_run( + "claude-spt", + reserved, + None, + None, + false, + false, + false, + None, + ); assert_eq!( code, 2, "the reserved id is an argument refusal (2), never a runtime failure (1)" @@ -3064,7 +3123,16 @@ mod reserved_id_tests { // walks on into the ordinary path and fails there for its own reason // (no such adapter in this empty home), which is a different code. assert_ne!( - super::cmd_endpoint_run("claude-spt", "ordinary", None, None, false, false, false, None), + super::cmd_endpoint_run( + "claude-spt", + "ordinary", + None, + None, + false, + false, + false, + None + ), 2, "only the reserved id takes the argument-refusal arm" ); @@ -3073,8 +3141,7 @@ mod reserved_id_tests { /// A perch on disk for `id`, carrying `adapter` as its recorded stamp — the /// minimum that makes an endpoint EXIST to the lifecycle verbs. fn fabricate_perch(id: &str, adapter: Option<&str>) { - let path = - spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); + let path = spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); std::fs::create_dir_all(&path).unwrap(); let mut info = spt_store::info::InfoJson::new(id, "2026-08-04T00:00:00Z", 0, "", "offline"); info.adapter = adapter.map(str::to_string); @@ -3104,7 +3171,9 @@ mod reserved_id_tests { "a refused verb minted nothing" ); assert!( - spt_daemon::config::DaemonConfig::load().startup_endpoints.is_empty(), + spt_daemon::config::DaemonConfig::load() + .startup_endpoints + .is_empty(), "...and persisted nothing" ); // ...except turning auto-start OFF, which must work on an endpoint that @@ -3120,7 +3189,10 @@ mod reserved_id_tests { .join("info.json"), ) .unwrap(); - assert_eq!(super::cmd_endpoint_create("taken", None, Some("x".into()), None), 2); + assert_eq!( + super::cmd_endpoint_create("taken", None, Some("x".into()), None), + 2 + ); assert_eq!( std::fs::read_to_string( spt_store::perch::resolve_perch_path("taken", spt_store::perch::ParentHint::Infer) @@ -3248,11 +3320,13 @@ mod verb_surface_route_table { Err(_) => return Door::Refused, }; let remembered = || recorded.map(str::to_string); - let resolved = |flag: Option, remembered: Option| { - match pick_adapter(flag, remembered, &[]) { - AdapterPick::Use(a) => Some(a), - AdapterPick::Undecidable(_) => None, - } + let resolved = |flag: Option, remembered: Option| match pick_adapter( + flag, + remembered, + &[], + ) { + AdapterPick::Use(a) => Some(a), + AdapterPick::Undecidable(_) => None, }; let action = match cli.cmd { None => return Door::NoVerb, @@ -3330,13 +3404,26 @@ mod verb_surface_route_table { let rows: &[(&[&str], Option<&str>, Door)] = &[ // ── create: the ONLY mint ── ( - &["spt", "endpoint", "create", "doyle", "--adapter", "claude-spt"], + &[ + "spt", + "endpoint", + "create", + "doyle", + "--adapter", + "claude-spt", + ], None, step(Step::Create), ), ( &[ - "spt", "endpoint", "create", "doyle", "--adapter", "claude-spt", "--subnet", + "spt", + "endpoint", + "create", + "doyle", + "--adapter", + "claude-spt", + "--subnet", "home-net", ], None, @@ -3347,7 +3434,13 @@ mod verb_surface_route_table { ), ( &[ - "spt", "endpoint", "create", "doyle", "--adapter", "claude-spt", "--cwd", + "spt", + "endpoint", + "create", + "doyle", + "--adapter", + "claude-spt", + "--cwd", "/srv/proj", ], None, @@ -3361,7 +3454,10 @@ mod verb_surface_route_table { ( &["spt", "endpoint", "create", "doyle"], Some("claude-spt"), - Door::Step(Bringup { adapter: None, ..bringup(Step::Create) }), + Door::Step(Bringup { + adapter: None, + ..bringup(Step::Create) + }), ), // ── start: a NEW session on an endpoint that already exists ── ( @@ -3370,7 +3466,14 @@ mod verb_surface_route_table { step(Step::Start), ), ( - &["spt", "endpoint", "start", "doyle", "--adapter", "claude-spt"], + &[ + "spt", + "endpoint", + "start", + "doyle", + "--adapter", + "claude-spt", + ], None, step(Step::Start), ), @@ -3379,7 +3482,10 @@ mod verb_surface_route_table { ( &["spt", "endpoint", "start", "doyle", "--adapter", "ccs"], Some("claude-spt"), - Door::Step(Bringup { adapter: Some("ccs".into()), ..bringup(Step::Start) }), + Door::Step(Bringup { + adapter: Some("ccs".into()), + ..bringup(Step::Start) + }), ), ( &["spt", "endpoint", "start", "doyle", "--cwd", "/srv/proj"], @@ -3393,7 +3499,10 @@ mod verb_surface_route_table { ( &["spt", "endpoint", "start", "doyle"], None, - Door::Step(Bringup { adapter: None, ..bringup(Step::Start) }), + Door::Step(Bringup { + adapter: None, + ..bringup(Step::Start) + }), ), // ── resume: the endpoint's LATEST session ── ( @@ -3405,16 +3514,26 @@ mod verb_surface_route_table { ( &["spt", "endpoint", "auto-start", "doyle"], None, - Door::AutoStart { id: "doyle".into(), off: false }, + Door::AutoStart { + id: "doyle".into(), + off: false, + }, ), ( &["spt", "endpoint", "auto-start", "doyle", "--off"], None, - Door::AutoStart { id: "doyle".into(), off: true }, + Door::AutoStart { + id: "doyle".into(), + off: true, + }, ), // ── go: the top-level ladder verb, and what a generated launcher // now bakes (`spt go `). ── - (&["spt", "go", "doyle"], None, Door::Go { id: "doyle".into() }), + ( + &["spt", "go", "doyle"], + None, + Door::Go { id: "doyle".into() }, + ), // Bare `spt` — the picker's own entry, which this lane does not // touch and which must therefore keep parsing to no subcommand. (&["spt"], None, Door::NoVerb), @@ -3535,7 +3654,10 @@ mod lifecycle_verb_decisions { AdapterPick::Use("claude-spt".into()) ); // Nothing named, nothing remembered, exactly one installed → that one. - assert_eq!(pick_adapter(None, None, &one), AdapterPick::Use("claude-spt".into())); + assert_eq!( + pick_adapter(None, None, &one), + AdapterPick::Use("claude-spt".into()) + ); // Several installed and nothing to choose between them → REFUSE, and // carry the set so the refusal can show it. assert_eq!( @@ -3544,7 +3666,10 @@ mod lifecycle_verb_decisions { ); // None installed → also undecidable, and distinguishable by the empty // set (the refusal wording differs: there is nothing to name). - assert_eq!(pick_adapter(None, None, &[]), AdapterPick::Undecidable(vec![])); + assert_eq!( + pick_adapter(None, None, &[]), + AdapterPick::Undecidable(vec![]) + ); } // [unit->REQ-USHER-LIFECYCLE-VERBS] "its most-recent adapter in its @@ -3558,29 +3683,44 @@ mod lifecycle_verb_decisions { // No row at all → the record answers both. assert_eq!( remembered_defaults(record(), None), - SessionDefaults { adapter: s("claude-spt"), cwd: s("/old/proj") } + SessionDefaults { + adapter: s("claude-spt"), + cwd: s("/old/proj") + } ); // A fully-stamped row supersedes the record on both fields. assert_eq!( remembered_defaults(record(), Some(&row(Some("ccs"), Some("/new/proj")))), - SessionDefaults { adapter: s("ccs"), cwd: s("/new/proj") } + SessionDefaults { + adapter: s("ccs"), + cwd: s("/new/proj") + } ); // A pre-migration row (no adapter, no cwd) supersedes NEITHER — this is // the arm a whole-struct "newest wins" would get wrong, silently // sending the next session to the daemon's cwd under a guessed adapter. assert_eq!( remembered_defaults(record(), Some(&row(None, None))), - SessionDefaults { adapter: s("claude-spt"), cwd: s("/old/proj") } + SessionDefaults { + adapter: s("claude-spt"), + cwd: s("/old/proj") + } ); // A half-stamped row: the field it carries wins, the field it lacks // falls back. Per-field, not all-or-nothing. assert_eq!( remembered_defaults(record(), Some(&row(Some("ccs"), None))), - SessionDefaults { adapter: s("ccs"), cwd: s("/old/proj") } + SessionDefaults { + adapter: s("ccs"), + cwd: s("/old/proj") + } ); assert_eq!( remembered_defaults(record(), Some(&row(None, Some("/new/proj")))), - SessionDefaults { adapter: s("claude-spt"), cwd: s("/new/proj") } + SessionDefaults { + adapter: s("claude-spt"), + cwd: s("/new/proj") + } ); // Nothing recorded anywhere → nothing remembered (the caller refuses). assert_eq!(remembered_defaults(None, None), SessionDefaults::default()); @@ -3611,44 +3751,79 @@ mod lifecycle_verb_decisions { // another node — reading local state for either would answer the wrong // question confidently. assert_eq!( - go_ladder(GoState { defers_to_rc: true, known: false, ..state() }), + go_ladder(GoState { + defers_to_rc: true, + known: false, + ..state() + }), GoStep::DeferToRc ); assert_eq!( - go_ladder(GoState { defers_to_rc: true, live: true, controlled: true, ..state() }), + go_ladder(GoState { + defers_to_rc: true, + live: true, + controlled: true, + ..state() + }), GoStep::DeferToRc ); // Unknown here → refuse. A typo must not mint. assert_eq!( - go_ladder(GoState { known: false, has_session: true, ..state() }), + go_ladder(GoState { + known: false, + has_session: true, + ..state() + }), GoStep::RefuseUnknown ); // Online, nobody driving → attach. - assert_eq!(go_ladder(GoState { live: true, ..state() }), GoStep::Attach); + assert_eq!( + go_ladder(GoState { + live: true, + ..state() + }), + GoStep::Attach + ); // Online, SOMEONE driving → confirm first. This rung is asked BEFORE // the plain attach; if the order slipped, `go` would kick a controller // off with nobody having agreed to it. assert_eq!( - go_ladder(GoState { live: true, controlled: true, ..state() }), + go_ladder(GoState { + live: true, + controlled: true, + ..state() + }), GoStep::ConfirmThenTake ); // A live endpoint is attached to even if it also has sessions on record // — every live endpoint does, so a ladder that asked the ledger first // would re-spawn over a running one. assert_eq!( - go_ladder(GoState { live: true, has_session: true, suspended: true, ..state() }), + go_ladder(GoState { + live: true, + has_session: true, + suspended: true, + ..state() + }), GoStep::Attach ); // Resting → wake in place, not a fresh bringup: its state is already // there. Asked before the ledger, since a suspended endpoint has // sessions too. assert_eq!( - go_ladder(GoState { suspended: true, has_session: true, ..state() }), + go_ladder(GoState { + suspended: true, + has_session: true, + ..state() + }), GoStep::WakeThenAttach ); // Offline WITH a session on record → resume the latest. assert_eq!( - go_ladder(GoState { has_session: true, ..state() }), + go_ladder(GoState { + has_session: true, + ..state() + }), GoStep::ResumeThenAttach ); // Offline with none → mint the first one (operator-ruled). @@ -3741,7 +3916,13 @@ mod retired_verb_pre_scan { #[test] fn the_retired_verb_refuses_with_a_pointer_a_generic_error_cannot_fake() { let msg = retired_verb_refusal(&argv(&[ - "spt", "endpoint", "run", "--adapter", "claude-spt", "--id", "doyle", + "spt", + "endpoint", + "run", + "--adapter", + "claude-spt", + "--id", + "doyle", ])) .expect("the retired verb is refused before clap is ever built"); for verb in REPLACEMENTS { @@ -3790,12 +3971,12 @@ mod retired_verb_pre_scan { #[test] fn the_pre_scan_reads_the_verb_position_only() { let untouched: &[&[&str]] = &[ - &["spt", "daemon", "run"], // another noun's `run` - &["spt", "send", "run"], // a message TO an endpoint named run - &["spt", "send", "endpoint", "run"], // ...whose body is the two words - &["spt", "endpoint", "start", "run"], // an endpoint named `run`, started - &["spt", "endpoint", "create", "run"], // ...and minted - &["spt", "go", "run"], // ...and gone to + &["spt", "daemon", "run"], // another noun's `run` + &["spt", "send", "run"], // a message TO an endpoint named run + &["spt", "send", "endpoint", "run"], // ...whose body is the two words + &["spt", "endpoint", "start", "run"], // an endpoint named `run`, started + &["spt", "endpoint", "create", "run"], // ...and minted + &["spt", "go", "run"], // ...and gone to &["spt", "endpoint", "list"], &["spt", "--json", "endpoint", "list"], &["spt"], @@ -3891,7 +4072,9 @@ fn refuse_undecidable_adapter(id: &str, registered: &[String]) -> i32 { /// PROVISIONAL is not a resumable session (REQ-RESUME-HARNESS-SESSION-ID) — the /// harness never knew it — so it can never satisfy this either. // [impl->REQ-USHER-LIFECYCLE-VERBS] -fn latest_harness_session(perch_path: &std::path::Path) -> Option { +fn latest_harness_session( + perch_path: &std::path::Path, +) -> Option { spt_store::sessions::read_all(perch_path) .into_iter() .rev() @@ -4154,7 +4337,11 @@ fn cmd_endpoint_auto_start(id: &str, off: bool) -> i32 { Ok(replaced) => { eprintln!( "ENDPOINT_AUTOSTART_SAVED:{id} adapter={adapter}{}", - if replaced { " (replaced prior entry)" } else { "" } + if replaced { + " (replaced prior entry)" + } else { + "" + } ); 0 } @@ -4258,13 +4445,29 @@ enum GoStep { // [impl->REQ-USHER-LIFECYCLE-VERBS] fn go_ladder(s: GoState) -> GoStep { match s { - GoState { defers_to_rc: true, .. } => GoStep::DeferToRc, + GoState { + defers_to_rc: true, .. + } => GoStep::DeferToRc, GoState { known: false, .. } => GoStep::RefuseUnknown, - GoState { live: true, controlled: true, .. } => GoStep::ConfirmThenTake, - GoState { live: true, controlled: false, .. } => GoStep::Attach, - GoState { suspended: true, .. } => GoStep::WakeThenAttach, - GoState { has_session: true, .. } => GoStep::ResumeThenAttach, - GoState { has_session: false, .. } => GoStep::MintThenAttach, + GoState { + live: true, + controlled: true, + .. + } => GoStep::ConfirmThenTake, + GoState { + live: true, + controlled: false, + .. + } => GoStep::Attach, + GoState { + suspended: true, .. + } => GoStep::WakeThenAttach, + GoState { + has_session: true, .. + } => GoStep::ResumeThenAttach, + GoState { + has_session: false, .. + } => GoStep::MintThenAttach, } } @@ -4291,7 +4494,8 @@ fn confirm_kick(id: &str, controller: Option<&str>) -> bool { eprint!("'{id}' is being driven{who}. Kick them off and take control? [y/N]: "); let _ = std::io::Write::flush(&mut std::io::stderr()); let mut line = String::new(); - std::io::stdin().read_line(&mut line).is_ok() && matches!(line.trim(), "y" | "Y" | "yes" | "YES") + std::io::stdin().read_line(&mut line).is_ok() + && matches!(line.trim(), "y" | "Y" | "yes" | "YES") } /// The attach `go` performs on a rung it reached BECAUSE the endpoint is live. @@ -4473,29 +4677,29 @@ pub(crate) fn cmd_endpoint_run( // Resolve the harness adapter option (`[:profile]`) through the // merged view (split → parent lookup → overlay), exactly like shell spawn. let adapters_dir = spt_store::perch::adapters_dir(); - let (manifest, install_dir) = match spt_runtime::registry::resolve_option(&adapters_dir, adapter) - { - // The record's `source_dir` is the adapter install dir (W3a) — carried to - // the broker so a live adapter update can target this endpoint. - Ok((r, m)) if m.adapter.kind == spt_runtime::manifest::AdapterKind::Harness => { - (m, Some(r.source_dir)) - } - Ok(_) => { - eprintln!( - "ENDPOINT_RUN_NOT_HARNESS:{adapter}: not a kind=\"harness\" adapter — \ + let (manifest, install_dir) = + match spt_runtime::registry::resolve_option(&adapters_dir, adapter) { + // The record's `source_dir` is the adapter install dir (W3a) — carried to + // the broker so a live adapter update can target this endpoint. + Ok((r, m)) if m.adapter.kind == spt_runtime::manifest::AdapterKind::Harness => { + (m, Some(r.source_dir)) + } + Ok(_) => { + eprintln!( + "ENDPOINT_RUN_NOT_HARNESS:{adapter}: not a kind=\"harness\" adapter — \ the endpoint lifecycle verbs bring up harness endpoints (shells use \ `shell spawn`)" - ); - return 1; - } - Err(e) => { - eprintln!( - "ENDPOINT_RUN_ADAPTER_UNREGISTERED:{adapter}: not an active registered \ + ); + return 1; + } + Err(e) => { + eprintln!( + "ENDPOINT_RUN_ADAPTER_UNREGISTERED:{adapter}: not an active registered \ harness adapter / valid profile on this node ({e}; spt adapter list)" - ); - return 1; - } - }; + ); + return 1; + } + }; // B2 (REQ-RESUME-HARNESS-SESSION-ID): a fresh bringup mints a provisional // spawn-time session id; `--resume` must feed the native-resume template @@ -4509,7 +4713,8 @@ pub(crate) fn cmd_endpoint_run( let (is_resume, session_id) = match resume { None => (false, spt_daemon::harnesshost::mint_session_id()), Some(requested) => { - let perch = spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); + let perch = + spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); // sessions::last_k returns oldest→newest; the resolver wants newest-first. let mut ledger: Vec = spt_store::sessions::last_k(&perch, spt_store::sessions::MAX_LEDGER) @@ -4618,8 +4823,10 @@ pub(crate) fn cmd_endpoint_run( .or_else(|| { is_resume .then(|| { - let perch = - spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); + let perch = spt_store::perch::resolve_perch_path( + id, + spt_store::perch::ParentHint::Infer, + ); spt_store::info::read_info(&perch).and_then(|r| r.cwd) }) .flatten() @@ -4635,7 +4842,8 @@ pub(crate) fn cmd_endpoint_run( // multi-subnet node with no `--subnet` refuses HERE — before launch+await — // never the silent 25s online-timeout. A resume/rebind (a prior perch // exists) is left to the bind path. [impl->REQ-RUN-MULTISUBNET-HOME] - if let Err(code) = resolve_home_and_write_skeleton(id, adapter, subnet, project_cwd.as_deref()) { + if let Err(code) = resolve_home_and_write_skeleton(id, adapter, subnet, project_cwd.as_deref()) + { return code; } // RESUME UNBOUND STAMP (ADR-0042 decision 2): the skeleton write above @@ -4650,8 +4858,9 @@ pub(crate) fn cmd_endpoint_run( // broker's death observers (mark_offline → terminal_normalize). // [impl->REQ-RESUME-UNBOUND-STAMP] let perch_path = spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); - let unbound_rollback: Option = - spt_store::info::resume_unbound_stamp(&perch_path).ok().flatten(); + let unbound_rollback: Option = spt_store::info::resume_unbound_stamp(&perch_path) + .ok() + .flatten(); // `{node}` fill (REQ-MANIFEST-NODE-KEY): the CLI self-spawn has no daemon in-mem // label handle, so the shared resolver falls to the OS hostname — the same // self-label source the CLI uses everywhere (subnet self, member self). @@ -4799,7 +5008,10 @@ enum RunHomeDecision { /// Multi-subnet, no `--subnet`, INTERACTIVE → confirm the proposed default /// (Y/n); `default` is the MRU pick when it is still a member, else the first /// subnet. - Confirm { default: String, subnets: Vec }, + Confirm { + default: String, + subnets: Vec, + }, } /// Order subnet `names` by the `mru` preference list (recency-ordered, head = @@ -4846,7 +5058,10 @@ fn decide_run_home( RunHomeDecision::RefuseAmbiguous(ordered) } else { let default = ordered[0].clone(); - RunHomeDecision::Confirm { default, subnets: ordered } + RunHomeDecision::Confirm { + default, + subnets: ordered, + } } } } @@ -4866,15 +5081,14 @@ fn resolve_home_and_write_skeleton( project_cwd: Option<&str>, ) -> Result<(), i32> { use std::io::{IsTerminal, Write}; - let perch_path = - spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); + let perch_path = spt_store::perch::resolve_perch_path(id, spt_store::perch::ParentHint::Infer); if spt_store::info::read_info(&perch_path).is_some() { return Ok(()); // resume/rebind — the bind path owns home (immutable) } let store = spt_store::subnet::SubnetStore::load(); let interactive = std::io::stdin().is_terminal() && std::io::stderr().is_terminal(); - let project_id = project_cwd - .map(|c| spt_store::project::project_id_for_dir(std::path::Path::new(c))); + let project_id = + project_cwd.map(|c| spt_store::project::project_id_for_dir(std::path::Path::new(c))); let mru = spt_store::recent_home::mru_preference(project_id.as_deref()); let home = match decide_run_home( spt_store::home::assign_home(&store, subnet), @@ -5026,12 +5240,24 @@ mod run_on_live_tests { assert_eq!(run_on_live_decision(false, true, false), RunOnLive::Spawn); // Live + CREATE intent → typed conflict, attach-mode AND headless (the // create contract has no silent-ensure overload). - assert_eq!(run_on_live_decision(true, false, true), RunOnLive::CreateConflict); - assert_eq!(run_on_live_decision(true, true, true), RunOnLive::CreateConflict); + assert_eq!( + run_on_live_decision(true, false, true), + RunOnLive::CreateConflict + ); + assert_eq!( + run_on_live_decision(true, true, true), + RunOnLive::CreateConflict + ); // Live + RESUME intent + attach → reattach, not a 2nd session (B1/B4). - assert_eq!(run_on_live_decision(true, false, false), RunOnLive::Reattach); + assert_eq!( + run_on_live_decision(true, false, false), + RunOnLive::Reattach + ); // Live + RESUME intent + headless → refuse the duplicate (idempotent). - assert_eq!(run_on_live_decision(true, true, false), RunOnLive::RefuseAlreadyLive); + assert_eq!( + run_on_live_decision(true, true, false), + RunOnLive::RefuseAlreadyLive + ); } } @@ -5081,12 +5307,18 @@ mod run_home_tests { // INTERACTIVE, MRU stale (not a current member) → first subnet default. assert_eq!( decide_run_home(Err(HomeError::Ambiguous(names.clone())), true, &mru_stale), - RunHomeDecision::Confirm { default: "homenet".into(), subnets: names.clone() } + RunHomeDecision::Confirm { + default: "homenet".into(), + subnets: names.clone() + } ); // INTERACTIVE, no MRU at all → first subnet default, original order. assert_eq!( decide_run_home(Err(HomeError::Ambiguous(names.clone())), true, none), - RunHomeDecision::Confirm { default: "homenet".into(), subnets: names } + RunHomeDecision::Confirm { + default: "homenet".into(), + subnets: names + } ); } @@ -5239,10 +5471,16 @@ fn cmd_fork(src: &str, new_id: &str, subnet: &str, delete_source: bool) -> i32 { ForkLocalOutcome::Forked => {} ForkLocalOutcome::BadRequest(why) => { eprintln!("BAD_FORK:{src} -> {new_id}: {why}"); - return if why.starts_with("invalid new id") { 2 } else { 1 }; + return if why.starts_with("invalid new id") { + 2 + } else { + 1 + }; } ForkLocalOutcome::NoSubnet => { - eprintln!("NO_SUBNET:{subnet} — this node is not a member; the fork's home must be held"); + eprintln!( + "NO_SUBNET:{subnet} — this node is not a member; the fork's home must be held" + ); return 1; } ForkLocalOutcome::NoSource => { @@ -5637,7 +5875,10 @@ fn cmd_monic(action: MonicCmd, json: bool) -> i32 { id: e.id.clone(), triggers: e.monic.as_ref().map(|m| m.triggers.clone()), text: e.monic.as_ref().map(|m| m.text.clone()), - origin: e.monic.as_ref().map(|m| monic_origin_word(m.origin).to_string()), + origin: e + .monic + .as_ref() + .map(|m| monic_origin_word(m.origin).to_string()), set_ms: e.monic.as_ref().map(|m| m.set_ms), unreadable: e.is_unreadable(), }) @@ -6466,7 +6707,10 @@ fn cmd_endpoint_list( .map(|n| { ( n.clone(), - subnets.find(n).map(|s| s.hide_new_endpoints).unwrap_or(false), + subnets + .find(n) + .map(|s| s.hide_new_endpoints) + .unwrap_or(false), ) }) .collect(), @@ -6523,8 +6767,7 @@ fn cmd_endpoint_list( // local perch — the same source the human column uses. // [impl->REQ-ENDPOINT-LIST-PROJECT-COL] let project = - crate::picker::data::indexed_latest_project_ref(&index, &p.id) - .map(|pr| pr.id); + crate::picker::data::indexed_latest_project_ref(&index, &p.id).map(|pr| pr.id); // The roster-survey activity key (ADR-0048): one sentinel read // per LOCAL row, through the shared vocabulary source. An // unbound perch reports nothing — see the field doc. @@ -6569,13 +6812,19 @@ fn cmd_endpoint_list( // [impl->REQ-UNLISTED-RENDER] the machine leg of the family, built // from the same gather the human leg uses — reader parity is what // REQ-LIST-JSON-LIVENESS-PARITY already demands of this function. - let local_ids: std::collections::BTreeSet = - local.iter().map(|p: &LocalPerchJson| p.id.clone()).collect(); + let local_ids: std::collections::BTreeSet = local + .iter() + .map(|p: &LocalPerchJson| p.id.clone()) + .collect(); // [impl->REQ-UNLISTED-PRESENCE-PROBE] the machine leg asks the same // question the human leg does — reader parity covers the presence word // exactly as it covers the state word. let unlisted = unlisted_json(&probe_unlisted(gather_unlisted( - ®s, &subnets, &vis, &names_for_unlisted, local_ids, + ®s, + &subnets, + &vis, + &names_for_unlisted, + local_ids, ))); return print_json(&EndpointListJson { self_pin, @@ -6608,10 +6857,14 @@ fn cmd_endpoint_list( // UNBOUND surfaces here too (REQ-ENDPOINT-UNBOUND-ATTACH): the Self // pin must not read a live pre-bind session as plain alive=false. let unbound = if p.unbound { " UNBOUND" } else { "" }; - format!("{} ready={} alive={}{}", p.state, p.ready, p.alive, unbound) + format!( + "{} ready={} alive={}{}", + p.state, p.ready, p.alive, unbound + ) }) .unwrap_or_else(|| "(no local perch)".to_string()); - let info = spt_store::info::read_info(&perch::resolve_perch_path(&self_id, ParentHint::Infer)); + let info = + spt_store::info::read_info(&perch::resolve_perch_path(&self_id, ParentHint::Infer)); let desc = info.as_ref().and_then(|rec| rec.resources.clone()); // The harness-reachable psyche-host-failure annotation (v0.8.1, // REQ-HAZARD-LIVEHOST-BOOT-RACE): an online live agent whose Psyche failed @@ -6630,17 +6883,17 @@ fn cmd_endpoint_list( println!( "{}", render_self_pin( - &self_id, - &state, - desc.as_deref(), - Some(self_node_ident.as_str()), - self_pin_annotations( - phe.as_ref(), - tf.as_deref(), - he.as_deref(), - registered_drop_dir(info.as_ref()).as_deref(), - ), - ) + &self_id, + &state, + desc.as_deref(), + Some(self_node_ident.as_str()), + self_pin_annotations( + phe.as_ref(), + tf.as_deref(), + he.as_deref(), + registered_drop_dir(info.as_ref()).as_deref(), + ), + ) ); } @@ -6670,8 +6923,7 @@ fn cmd_endpoint_list( // #8: the LATEST project (the indexed history head) — looked up // here, then passed in (this_node_cell stays pure over its inputs). // [impl->REQ-ENDPOINT-LIST-PROJECT-COL] - let project_ref = - crate::picker::data::indexed_latest_project_ref(&index, &p.id); + let project_ref = crate::picker::data::indexed_latest_project_ref(&index, &p.id); this_node_cell(&p, rec.as_ref(), project_ref) }) .collect(); @@ -6726,7 +6978,10 @@ fn cmd_endpoint_list( .map(|n| { ( n.clone(), - subnets.find(n).map(|s| s.hide_new_endpoints).unwrap_or(false), + subnets + .find(n) + .map(|s| s.hide_new_endpoints) + .unwrap_or(false), ) }) .collect(), @@ -6845,7 +7100,10 @@ fn gather_unlisted( .map(|n| { ( n.clone(), - subnets.find(n).map(|s| s.hide_new_endpoints).unwrap_or(false), + subnets + .find(n) + .map(|s| s.hide_new_endpoints) + .unwrap_or(false), ) }) .collect(), @@ -6860,9 +7118,7 @@ fn gather_unlisted( let mut listed: std::collections::BTreeSet = std::collections::BTreeSet::new(); for name in names { let Some(reg) = regs.get(name) else { continue }; - for row in - spt_net::net::registry::resource_projection(reg, |id| excl.in_subnet(name, id)) - { + for row in spt_net::net::registry::resource_projection(reg, |id| excl.in_subnet(name, id)) { listed.insert(row.endpoint_id); } } @@ -7158,13 +7414,16 @@ fn instance_cell_from_resource(r: &spt_net::net::registry::ResourceRow) -> Insta // #8: the LATEST project = the #4-gossiped recent_projects head. IDs only cross // the wire (no dir), so the disambiguation degrades this to the bare ID. // [impl->REQ-ENDPOINT-LIST-PROJECT-COL] - project_ref: r.recent_projects.first().map(|id| crate::picker::model::ProjectRef { - id: id.clone(), - dir: String::new(), - // IDs only cross the wire (no dir, no URL) → display falls back to the id - // verbatim (REQ-PICKER-PROJECT-DISPLAY-NAME honest fallback). - display: id.clone(), - }), + project_ref: r + .recent_projects + .first() + .map(|id| crate::picker::model::ProjectRef { + id: id.clone(), + dir: String::new(), + // IDs only cross the wire (no dir, no URL) → display falls back to the id + // verbatim (REQ-PICKER-PROJECT-DISPLAY-NAME honest fallback). + display: id.clone(), + }), } } @@ -7280,7 +7539,11 @@ fn format_instance_rows(cells: &[InstanceCell], detail: bool, color: bool) -> St .map(|(c, project)| { // A corrupt record renders as the SUSPENDED square + a CORRUPT word so it // reads as an actionable record condition, not plain offline clutter. - let disp = if c.corrupt { EpDisplay::Suspended } else { c.display }; + let disp = if c.corrupt { + EpDisplay::Suspended + } else { + c.display + }; let square = disp.square(color); // glyph beside the name (A6 c) let label = if c.corrupt { "CORRUPT".to_string() @@ -7304,9 +7567,21 @@ fn format_instance_rows(cells: &[InstanceCell], detail: bool, color: bool) -> St ) }) .collect(); - let id_w = rendered.iter().map(|c| c.0.chars().count()).max().unwrap_or(0); - let proj_w = rendered.iter().map(|c| c.2.chars().count()).max().unwrap_or(0); - let type_w = rendered.iter().map(|c| c.3.chars().count()).max().unwrap_or(0); + let id_w = rendered + .iter() + .map(|c| c.0.chars().count()) + .max() + .unwrap_or(0); + let proj_w = rendered + .iter() + .map(|c| c.2.chars().count()) + .max() + .unwrap_or(0); + let type_w = rendered + .iter() + .map(|c| c.3.chars().count()) + .max() + .unwrap_or(0); let status_w = rendered.iter().map(|c| c.5).max().unwrap_or(0); let mut out = String::new(); for c in &rendered { @@ -7374,7 +7649,11 @@ fn filter_and_order(cells: &[InstanceCell], show_all: bool) -> (VecREQ-PICKER-REMOTE-WAKE] pub fn cmd_endpoint_wake_remote(id: &str, node: &str) -> i32 { - cmd_rest(&format!("{id}@{node}"), spt_daemon::RestEvent::Wake, "WOKE", true) + cmd_rest( + &format!("{id}@{node}"), + spt_daemon::RestEvent::Wake, + "WOKE", + true, + ) } fn cmd_rest(id: &str, event: spt_daemon::RestEvent, verb: &str, bare_remote_fallback: bool) -> i32 { @@ -7702,7 +7990,9 @@ fn dispatch_wan_rest(target: &str, tag: &str, verb: &str) -> i32 { 0 } crate::wansend::WanRestOutcome::NoReply { node } => { - eprintln!("{verb}_REFUSED:{target}: {node} closed the stream without a reply (access gate)"); + eprintln!( + "{verb}_REFUSED:{target}: {node} closed the stream without a reply (access gate)" + ); 1 } crate::wansend::WanRestOutcome::RemoteFail { node, detail } => { @@ -7981,7 +8271,10 @@ fn stop_live_session_guard(live_sessions: &[String], force: bool) -> Result<(), /// the failure is invisible from the only side that could see it. // [impl->REQ-BROKER-STOP-ENDPOINT-DENY] // [impl->REQ-BROKER-STOP-DENY-NAMES-BLAST] -fn broker_stop_endpoint_denial(ground: Option<&AgentGround>, residents: &[String]) -> Option { +fn broker_stop_endpoint_denial( + ground: Option<&AgentGround>, + residents: &[String], +) -> Option { let ground = ground?; // The blast radius, named. A refusal that says only "denied" teaches // nothing; one that names what was about to die explains itself. @@ -8550,36 +8843,34 @@ fn cmd_daemon_status(json: bool) -> i32 { stall_stats, self_net, ) = if running { - match spt_daemon::brain::Brain::cold_start( - &spt_daemon::broker_socket_name(), - now_ms(), - ) { - Ok(mut b) => { - // #41: keep the WHOLE net-status reply, not just - // `enabled` — the node's own dialable address (and the - // relay it is actually homed on) was reachable here all - // along and reached no surface. - let status = b.net_status().ok(); - let n = status.as_ref().map(|s| s.enabled).unwrap_or(true); - let stall = b.stall_evicts().ok().flatten(); - // Ok(Some)=version / Ok(None)=old broker (both a successful - // query) vs Err=couldn't query — keep them distinct so a - // transient IPC failure does not read as a definite stale. - let (bi, bq) = match b.broker_image_version() { - Ok(v) => (v, true), - Err(_) => (None, false), - }; - let (ci, cq) = match b.coordinator_image_version() { - Ok(v) => (v, true), - Err(_) => (None, false), - }; - (Some(n), bi, bq, ci, cq, stall, status) - } - Err(_) => (Some(true), None, false, None, false, None, None), + match spt_daemon::brain::Brain::cold_start(&spt_daemon::broker_socket_name(), now_ms()) + { + Ok(mut b) => { + // #41: keep the WHOLE net-status reply, not just + // `enabled` — the node's own dialable address (and the + // relay it is actually homed on) was reachable here all + // along and reached no surface. + let status = b.net_status().ok(); + let n = status.as_ref().map(|s| s.enabled).unwrap_or(true); + let stall = b.stall_evicts().ok().flatten(); + // Ok(Some)=version / Ok(None)=old broker (both a successful + // query) vs Err=couldn't query — keep them distinct so a + // transient IPC failure does not read as a definite stale. + let (bi, bq) = match b.broker_image_version() { + Ok(v) => (v, true), + Err(_) => (None, false), + }; + let (ci, cq) = match b.coordinator_image_version() { + Ok(v) => (v, true), + Err(_) => (None, false), + }; + (Some(n), bi, bq, ci, cq, stall, status) } - } else { - (None, None, false, None, false, None, None) - }; + Err(_) => (Some(true), None, false, None, false, None, None), + } + } else { + (None, None, false, None, false, None, None) + }; // [impl->REQ-SELF-ENDPOINT-ADDR-SURFACE] this node's own dialable // address and the relay it is homed on RIGHT NOW — read off the live // endpoint, never off `daemon.json`. The gap that motivated it: the @@ -8781,8 +9072,7 @@ fn cmd_daemon_status(json: bool) -> i32 { // [impl->REQ-PROJECT-INDEX-WRITER] W2 observability: the materialized // project index's writer health (index presence alone is not health). if let Some(line) = render_project_index_line( - spt_daemon::projwriter::read_stats_at(&spt_daemon::projwriter::stats_path()) - .as_ref(), + spt_daemon::projwriter::read_stats_at(&spt_daemon::projwriter::stats_path()).as_ref(), ) { println!("{line}"); } @@ -8804,7 +9094,11 @@ fn cmd_daemon_status(json: bool) -> i32 { { let svc = spt_daemon::service::platform_service(); if svc.detected() { - let active = if svc.is_active() { "active" } else { "inactive" }; + let active = if svc.is_active() { + "active" + } else { + "inactive" + }; println!("managed-by: {} ({active})", svc.label()); } else if let Some(hint) = svc.boot_hint() { println!("managed-by: manual — {hint}"); @@ -9000,7 +9294,10 @@ fn cmd_notify(body: Option, target: Option, from: Option // replicated row could in principle arrive already-expired): the row // is auto-dismissed instead of surfaced (ADR-0046 decision 5). Ok((row, spt_daemon::FirstFireOutcome::Expired { .. })) => { - println!("NOTIF_EXPIRED:{} (TTL passed; auto-dismissed)", row.notif_id); + println!( + "NOTIF_EXPIRED:{} (TTL passed; auto-dismissed)", + row.notif_id + ); 0 } Err(e) => { @@ -9136,7 +9433,10 @@ fn render_applied_message(version: u64, product_version: &str) -> String { } else { format!("Updated spt-core to v{product_version}.") }; - format!("{head}\nChangelog: {RELEASES_URL}\n{}", restart_required_notice()) + format!( + "{head}\nChangelog: {RELEASES_URL}\n{}", + restart_required_notice() + ) } /// Friendly already-applied message for `spt update apply` (F-025) — mirrors @@ -9298,9 +9598,10 @@ fn cmd_update_apply(finish: bool) -> i32 { // UNGUARDED on purpose: it hands off in place, the broker survives, and // the invoker's PTY does not die. // [impl->REQ-BROKER-STOP-ENDPOINT-DENY] - if let Some(msg) = - broker_stop_endpoint_denial(ceremony_agent_ground().as_ref(), &live_hosted_session_ids()) - { + if let Some(msg) = broker_stop_endpoint_denial( + ceremony_agent_ground().as_ref(), + &live_hosted_session_ids(), + ) { eprintln!("UPDATE_FINISH_REFUSED: {msg}"); return EXIT_REFUSED_NO_WORK; } @@ -9527,7 +9828,10 @@ fn land_staged_docs(cache: &spt_daemon::ReleaseCache) { let bundle_path = cache.docs_bundle_path(); let _ = std::fs::remove_dir_all(&staging); if let Err(e) = std::fs::create_dir_all(&staging) { - eprintln!("UPDATE_DOCS_SKIPPED: create {}: {e} — docs retry next fetch", staging.display()); + eprintln!( + "UPDATE_DOCS_SKIPPED: create {}: {e} — docs retry next fetch", + staging.display() + ); return; } let mut keys = std::collections::BTreeMap::new(); @@ -9565,9 +9869,7 @@ fn land_staged_docs(cache: &spt_daemon::ReleaseCache) { if docs_dir.exists() { if let Err(e) = std::fs::rename(&docs_dir, &old) { let _ = std::fs::remove_dir_all(&staging); - eprintln!( - "UPDATE_DOCS_SKIPPED: retire old docs: {e} — docs retry next fetch" - ); + eprintln!("UPDATE_DOCS_SKIPPED: retire old docs: {e} — docs retry next fetch"); return; } } @@ -9804,9 +10106,7 @@ fn gh_status() -> GhStatus { None, ) { Ok(out) if out.success() => GhStatus::Available, - Err(spt_runtime::RuntimeError::Spawn(e)) - if e.kind() == std::io::ErrorKind::NotFound => - { + Err(spt_runtime::RuntimeError::Spawn(e)) if e.kind() == std::io::ErrorKind::NotFound => { GhStatus::Missing } _ => GhStatus::Unauthed, @@ -9903,7 +10203,10 @@ fn open_in_browser(url: &str) -> std::io::Result<()> { } #[cfg(target_os = "macos")] { - std::process::Command::new("open").arg(url).spawn().map(|_| ()) + std::process::Command::new("open") + .arg(url) + .spawn() + .map(|_| ()) } #[cfg(all(unix, not(target_os = "macos")))] { @@ -10266,12 +10569,8 @@ fn fetch_release_asset_bytes( EffectiveTransport::Gh => { std::fs::create_dir_all(scratch_dir).map_err(|e| e.to_string())?; let (template, keys) = gh_download_command(repo, tag, asset, scratch_dir); - match spt_runtime::run_bounded_command( - &template, - &keys, - Duration::from_secs(300), - None, - ) { + match spt_runtime::run_bounded_command(&template, &keys, Duration::from_secs(300), None) + { Ok(out) if out.success() => { let path = scratch_dir.join(asset); let bytes = std::fs::read(&path).map_err(|e| e.to_string()); @@ -10350,7 +10649,10 @@ fn classify_archive_layout(top_level_names: &[String]) -> ArchiveLayout { // [impl->REQ-INSTALL-9] fn tar_extract_all(archive: &std::path::Path, dest: &std::path::Path) -> Result<(), ExtractError> { let keys = std::collections::BTreeMap::from([ - ("archive".to_string(), archive.to_string_lossy().into_owned()), + ( + "archive".to_string(), + archive.to_string_lossy().into_owned(), + ), ("dest".to_string(), dest.to_string_lossy().into_owned()), ]); match spt_runtime::run_bounded_command( @@ -10430,7 +10732,9 @@ fn extract_release_archive( let staging = match dest.parent() { Some(parent) => parent.join(format!( "{}.spt-stage", - dest.file_name().map(|n| n.to_string_lossy()).unwrap_or_default() + dest.file_name() + .map(|n| n.to_string_lossy()) + .unwrap_or_default() )), None => dest.with_extension("spt-stage"), }; @@ -10706,7 +11010,8 @@ fn cmd_update_fetch(channel: Option, tag: Option, apply: bool) - // (REQ-UPDATE-FETCH-CURRENT-UX). Classify and report it as such; with // --apply, install an already-staged set instead of printing the hint // (REQ-UPDATE-FETCH-APPLY-FLAG). - let class = classify_fetch_reject(&reason, cache.applied_version(), cache.staged_version()); + let class = + classify_fetch_reject(&reason, cache.applied_version(), cache.staged_version()); return match fetch_reject_action(class, apply) { FetchAction::Apply => cmd_update_apply(false), FetchAction::DoneOk => { @@ -10759,8 +11064,7 @@ fn cmd_update_fetch(channel: Option, tag: Option, apply: bool) - return 1; } }; - if let Err(reason) = - spt_daemon::release::verify_update_set_artifact(&meta, triple, &bytes) + if let Err(reason) = spt_daemon::release::verify_update_set_artifact(&meta, triple, &bytes) { let _ = std::fs::remove_dir_all(&scratch); // Friendly Display, not the raw enum Debug (REQ-UPDATE-FETCH-CURRENT-UX); @@ -10792,9 +11096,9 @@ fn cmd_update_fetch(channel: Option, tag: Option, apply: bool) - eprintln!("UPDATE_DOCS_SKIPPED: stage: {e} — docs retry next fetch"); } } - Err(reason) => eprintln!( - "UPDATE_DOCS_SKIPPED: {reason} — docs retry next fetch" - ), + Err(reason) => { + eprintln!("UPDATE_DOCS_SKIPPED: {reason} — docs retry next fetch") + } }, Err(e) => eprintln!( "UPDATE_DOCS_SKIPPED: {} from {repo}: {e} — docs retry next fetch", @@ -11504,7 +11808,13 @@ pub(crate) fn cmd_send_verdict( // unconfirmed each read as their own non-zero failure, so a stale // route or a dropped payload can no longer masquerade as delivered. use crate::wansend::WanSendOutcome; - match crate::wansend::wan_send(&target, &from, sender_proven.as_deref(), Some(sender_origin), body) { + match crate::wansend::wan_send( + &target, + &from, + sender_proven.as_deref(), + Some(sender_origin), + body, + ) { WanSendOutcome::Sent { node, how } => { // "delivered" is the plain confirmed case; annotate spool/dup. if how == "delivered" { @@ -11913,7 +12223,10 @@ fn cmd_stop(id: &str) -> i32 { stale_row, } => { if let Some(root_pid) = stale_row { - eprintln!("{}", crate::teardown::stale_row_line("STOPPED", id, root_pid)); + eprintln!( + "{}", + crate::teardown::stale_row_line("STOPPED", id, root_pid) + ); } // The clauses name what ACTUALLY happened. The old line asserted // "address unregistered" on every marker-less stop, whether or not @@ -12220,8 +12533,10 @@ fn render_self_pin( // omitted line is honest, a guessed path is worse than silence. // [impl->REQ-ENDPOINT-DROP-DIR-SURFACE] if let Some(dir) = drop_dir.map(str::trim).filter(|d| !d.is_empty()) { - pin.push_str(&format!(" - commune drop dir: {dir}")); + pin.push_str(&format!( + " + commune drop dir: {dir}" + )); } // The broker-stamped input-translation fault (F-1, the F-030 seed): typed // input silently degraded while nothing rendered it — annotate with the @@ -12480,7 +12795,11 @@ fn decide_create_mode(open: bool, closed: bool, answer: Option<&str>) -> ModeCho if closed { return ModeChoice::Chosen(Mode::Closed); } - match answer.map(str::trim).map(str::to_ascii_lowercase).as_deref() { + match answer + .map(str::trim) + .map(str::to_ascii_lowercase) + .as_deref() + { Some("open") => ModeChoice::Chosen(Mode::Open), Some("closed") => ModeChoice::Chosen(Mode::Closed), _ => ModeChoice::Unstated, @@ -13146,7 +13465,11 @@ fn try_auto_elevate() -> Option { let os = elevation::current_os(); let is_unix = matches!(os, elevation::Os::Unix); let has_pkexec = is_unix && program_on_path("pkexec"); - let term = if is_unix { first_terminal_emulator() } else { None }; + let term = if is_unix { + first_terminal_emulator() + } else { + None + }; let path = elevation::decide_elevation_path( os, elevation::current(), @@ -13176,7 +13499,9 @@ fn try_auto_elevate() -> Option { let argv = elevation::terminal_argv(term, &exe, &argv_tail); match std::process::Command::new(term).args(&argv[1..]).spawn() { Ok(_) => { - eprintln!("Elevated terminal launched — complete the prompt in the new window."); + eprintln!( + "Elevated terminal launched — complete the prompt in the new window." + ); Some(0) } Err(_) => None, @@ -14237,7 +14562,10 @@ fn cmd_subnet_status(name: Option, nodes: bool, hints: bool, json: bool) // inbound_block_hint all flow through here). Node-id rows carry no // Markdown markers, so only the hints restyle/strip. // [impl->REQ-CLI-OUTPUT-MARKDOWN] - print!("{}", crate::helpfmt::render(&out, crate::helpfmt::stdout_color())); + print!( + "{}", + crate::helpfmt::render(&out, crate::helpfmt::stdout_color()) + ); let _ = std::io::stdout().flush(); return 0; } @@ -14331,8 +14659,7 @@ fn cmd_subnet_status(name: Option, nodes: bool, hints: bool, json: bool) }) .collect(); // [impl->REQ-SUBNET-STATUS-MODES] - let (declared, captured, pending) = - subnet_mode_facts(&store, &access_store, &sub_name); + let (declared, captured, pending) = subnet_mode_facts(&store, &access_store, &sub_name); json_subnets.push(SubnetRowJson { name: sub_name.clone(), node_count: node_rows.len(), @@ -14391,7 +14718,10 @@ fn cmd_subnet_status(name: Option, nodes: bool, hints: bool, json: bool) } // Same human status view as the non-`--nodes` branch — render the prose. // [impl->REQ-CLI-OUTPUT-MARKDOWN] - print!("{}", crate::helpfmt::render(&out, crate::helpfmt::stdout_color())); + print!( + "{}", + crate::helpfmt::render(&out, crate::helpfmt::stdout_color()) + ); let _ = std::io::stdout().flush(); 0 } @@ -14494,7 +14824,8 @@ fn prune_candidates(roster: &spt_store::roster::RosterStore, query: &str) -> Vec /// Elevation-gated, gate-first. Own identity refuses (leave owns that). // [impl->REQ-SUBNET-6] fn cmd_subnet_prune(node: &str) -> i32 { - if let Some(msg) = trust_mutation_refusal(elevation::current(), "pruning a node's roster rows") { + if let Some(msg) = trust_mutation_refusal(elevation::current(), "pruning a node's roster rows") + { if let Some(code) = try_auto_elevate() { return code; } @@ -14591,9 +14922,10 @@ const REVOKE_ROTATION_WINDOW_MS: u64 = 60 * 60 * 1000; /// `leave`). // [impl->REQ-MESH-4] fn cmd_subnet_revoke(nodes: &[String], force_rotate_seed: bool) -> i32 { - if let Some(msg) = - trust_mutation_refusal(elevation::current(), "revoking a node and rotating the seed") - { + if let Some(msg) = trust_mutation_refusal( + elevation::current(), + "revoking a node and rotating the seed", + ) { if let Some(code) = try_auto_elevate() { return code; } @@ -14967,8 +15299,9 @@ fn run_join_gate(phase: JoinPhase, has_code: bool) -> Option { if let Some(code) = try_auto_elevate() { return Some(code); } - let msg = join_elevation_refusal(elevation::current()) - .unwrap_or_else(|| "ELEVATION_REQUIRED: re-run elevated (run as administrator / root)".to_string()); + let msg = join_elevation_refusal(elevation::current()).unwrap_or_else(|| { + "ELEVATION_REQUIRED: re-run elevated (run as administrator / root)".to_string() + }); eprintln!("{}", with_elevation_hint(msg)); Some(EXIT_NOT_ELEVATED) } @@ -15525,7 +15858,10 @@ fn cmd_how_to(topic: Option<&str>, json: bool) -> i32 { // strip intact; only the human topic list is rendered. eprintln!( "{}", - render(&format!("NO_SUCH_TOPIC:{t} — topics:\n{}", list()), stderr_color()) + render( + &format!("NO_SUCH_TOPIC:{t} — topics:\n{}", list()), + stderr_color() + ) ); 2 } @@ -15656,11 +15992,13 @@ fn resolve_node_subject( // rather than typed from memory (doyle, 2026-08-22): a command name // in an operator-facing refusal is a pointer, and a wrong one sends // the reader somewhere the product does not go. - _ => Err("ACCESS_NO_NODE_IDENTITY: this node has no identity yet, so \ + _ => Err( + "ACCESS_NO_NODE_IDENTITY: this node has no identity yet, so \ `--node self` names nothing to write a rule about. Give it \ one with `spt subnet create ` or `spt subnet join`, \ then re-run this command." - .to_string()), + .to_string(), + ), }; } @@ -15965,8 +16303,9 @@ fn tuple_mutation( // edited an endpoint's rules through `--for` cannot undo it by pasting // the endpoint form, which is that endpoint's own seat. let undo = match (via_daemon_seat, &scope) { - (true, MutationScope::Endpoint(id)) => remove_command("node", &rule) - .replacen("remove", &format!("remove --for {id}"), 1), + (true, MutationScope::Endpoint(id)) => { + remove_command("node", &rule).replacen("remove", &format!("remove --for {id}"), 1) + } _ => remove_command(&owner, &rule), }; println!("to undo: {undo}"); @@ -16203,8 +16542,10 @@ fn fork_without_discover( let roster = spt_store::roster::RosterStore::load(); let subnets = spt_store::subnet::SubnetStore::load(); match &rule.subject { - Subject::Node { node } => (!node_sees_endpoint_with(store, endpoint, node, &roster, &subnets)) - .then(|| ForkDiscoverGap::Node(node.clone())), + Subject::Node { node } => { + (!node_sees_endpoint_with(store, endpoint, node, &roster, &subnets)) + .then(|| ForkDiscoverGap::Node(node.clone())) + } Subject::SubnetWildcard { subnet } => { let members: Vec = roster .members_in(subnet) @@ -16408,8 +16749,7 @@ fn inert_grant_with( if nodes.is_empty() { return Some(InertGrant::NotEvaluated { subject, - why: "no machine resolved for this subject, so there was nothing to ask" - .to_string(), + why: "no machine resolved for this subject, so there was nothing to ask".to_string(), }); } // An empty surface list means EVERY surface, so the question is asked of @@ -16607,9 +16947,11 @@ fn resolve_knocker(for_endpoint: Option<&str>) -> Result { // Classified as an endpoint but unable to name itself: refuse // rather than silently fall back to the user default, which would // be an agent knocking as the machine's humans. - _ => Err("KNOCK_UNPROVEN: this session classifies as an agent but resolves \ + _ => Err( + "KNOCK_UNPROVEN: this session classifies as an agent but resolves \ to no endpoint — nothing can be stamped as the knocker" - .to_string()), + .to_string(), + ), }, MsgOrigin::LocalUserCli => Ok(Knocker::User), } @@ -16645,7 +16987,10 @@ fn knock_route_bare( // args-with-subcommand refusal below, either of which would talk about // argument placement when the operator's problem is the word. if let Some(action) = action { - if target.is_some() || surfaces.is_some() || for_endpoint.is_some() || send_only + if target.is_some() + || surfaces.is_some() + || for_endpoint.is_some() + || send_only || send_receive { return Err(format!( @@ -16666,9 +17011,11 @@ fn knock_route_bare( send_only, send_receive, }), - None => Err("KNOCK_NO_TARGET: name the endpoint to knock (`spt knock `), or \ + None => Err( + "KNOCK_NO_TARGET: name the endpoint to knock (`spt knock `), or \ pick a subcommand — `send`, `list`, `approve`, `deny`, `new-code`, `redeem`" - .to_string()), + .to_string(), + ), } } @@ -16747,7 +17094,7 @@ fn knock_retired_flag(verb: &str, old: &str) -> String { let remedy = match verb { "approve" | "new-code" => String::from( "an approval and a mint declare no directionality at all — accepting is your own \ - side's act. To reach them back, knock back: `spt knock --send-receive`" + side's act. To reach them back, knock back: `spt knock --send-receive`", ), _ => format!("say {new}"), }; @@ -16846,13 +17193,7 @@ fn cmd_knock(action: KnockCmd) -> i32 { admit_node, subnet, monic, - } => cmd_knock_new_code( - surfaces, - for_node, - admit_node, - &subnet, - monic.as_deref(), - ), + } => cmd_knock_new_code(surfaces, for_node, admit_node, &subnet, monic.as_deref()), KnockCmd::Redeem { code, send_only, @@ -16949,7 +17290,10 @@ fn knock_random_hex(bytes: usize) -> String { /// operator reads on screen are one fact, not two that can disagree. // [impl->REQ-KNOCK-CODE-SEALED] fn knock_self_node_short() -> Option<[u8; spt_net::net::codeseal::NODE_SHORT_LEN]> { - let full = spt_store::nodeid::load_or_create().ok()?.public_key().to_bytes(); + let full = spt_store::nodeid::load_or_create() + .ok()? + .public_key() + .to_bytes(); let mut short = [0u8; spt_net::net::codeseal::NODE_SHORT_LEN]; short.copy_from_slice(&full[..spt_net::net::codeseal::NODE_SHORT_LEN]); Some(short) @@ -17561,7 +17905,10 @@ fn cmd_knock_send( if let Some(note) = narrow_note { println!(" = {note}"); } - println!(" expires in {} hours if unanswered", KNOCK_TTL_MS / 3_600_000); + println!( + " expires in {} hours if unanswered", + KNOCK_TTL_MS / 3_600_000 + ); if mutual { // This is the LOCAL landing: the approval runs against this same store, // so the pre-authorization is genuinely there to be consumed. @@ -17622,7 +17969,10 @@ fn cmd_knock_list(for_endpoint: Option<&str>, json: bool) -> i32 { }) }) .collect(); - println!("{}", serde_json::to_string_pretty(&rows).unwrap_or_default()); + println!( + "{}", + serde_json::to_string_pretty(&rows).unwrap_or_default() + ); return 0; } @@ -17647,14 +17997,21 @@ fn cmd_knock_list(for_endpoint: Option<&str>, json: bool) -> i32 { k.id, k.knocker, knock_surface_words(&k.surfaces), - if k.mutual { ", offers send-receive" } else { "" } + if k.mutual { + ", offers send-receive" + } else { + "" + } ); match access .as_ref() .map(|s| approval_form(s, k, &k.surfaces, authority)) { Some(ApprovalForm::AsRequested) => { - println!(" approve: spt knock approve {} --approve-requested", k.id); + println!( + " approve: spt knock approve {} --approve-requested", + k.id + ); } Some(ApprovalForm::AdmitNode { node }) => { println!( @@ -17793,7 +18150,10 @@ fn cmd_knock_deny(id: &str) -> i32 { // [impl->REQ-ACL-ORIGIN-QUALIFIER] fn approval_subject( knock: &spt_store::knock::Knock, -) -> (spt_store::access::Subject, spt_store::access::OriginQualifier) { +) -> ( + spt_store::access::Subject, + spt_store::access::OriginQualifier, +) { use spt_store::access::{OriginQualifier, Subject}; if knock.as_user { ( @@ -18269,9 +18629,11 @@ fn cmd_knock_approve( // The knocker's OWN pre-authorization, consumed exactly once at // answer-receipt — never on a refusal, which granted nothing to reciprocate. let mut reverse_opened = false; - if !matches!(outcome, ApproveOutcome::Refused { .. }) && knocks + if !matches!(outcome, ApproveOutcome::Refused { .. }) + && knocks .armed_mutual(spt_store::knock::PreAuthKey::Knock, id) - .is_some() { + .is_some() + { let pre = knocks .armed_mutual(spt_store::knock::PreAuthKey::Knock, id) .cloned() @@ -18428,7 +18790,10 @@ fn answer_receipt_applied(knocker: &str) -> String { /// Names the RECEIPT alone as what failed: a reader who takes this for a failed /// approval would re-approve something already granted. // [impl->REQ-KNOCK-ANSWER-RECEIPT] -fn answer_receipt_undelivered(knocker: &str, outcome: &crate::wansend::AnswerSendOutcome) -> String { +fn answer_receipt_undelivered( + knocker: &str, + outcome: &crate::wansend::AnswerSendOutcome, +) -> String { use crate::wansend::AnswerSendOutcome as A; let why = match outcome { A::Unconfirmed { node } => { @@ -18556,7 +18921,8 @@ fn cmd_knock_new_code( let (target, tier) = if for_node { // A node-target code grants what no single endpoint owns, so only the // engine room may mint one. - let is_er = matches!(&minter, Knocker::Endpoint(id) if spt_store::engineroom::is_engine_room(id)); + let is_er = + matches!(&minter, Knocker::Endpoint(id) if spt_store::engineroom::is_engine_room(id)); if !is_er { eprintln!( "KNOCK_FOR_NODE_IS_ENGINE_ROOM_ONLY: a node-target code grants what no \ @@ -18723,7 +19089,10 @@ fn cmd_knock_new_code( println!("minted an invite code for {target}:"); println!(" {handed}"); println!(" grants: {}", knock_surface_words(&surfaces)); - println!(" single use, expires in {} hours", KNOCK_TTL_MS / 3_600_000); + println!( + " single use, expires in {} hours", + KNOCK_TTL_MS / 3_600_000 + ); for line in mint_reach_lines(&sealing) { println!(" {line}"); } @@ -19051,8 +19420,10 @@ fn cmd_knock_redeem(code: &str, mutual: bool) -> i32 { consumed: false, }); if let Err(e) = knocks.save() { - eprintln!("KNOCK_FAIL: the send-receive pre-authorization could not be recorded ({e}) — \ - nothing was presented, so the code is unspent"); + eprintln!( + "KNOCK_FAIL: the send-receive pre-authorization could not be recorded ({e}) — \ + nothing was presented, so the code is unspent" + ); return 1; } } @@ -19255,7 +19626,9 @@ fn redeem_local(code: &str, mutual: bool) -> i32 { RedeemError::Unknown | RedeemError::Expired => { "that code is not valid (unknown or expired)" } - RedeemError::AlreadyConsumed => "that code has already been used — codes are single-use", + RedeemError::AlreadyConsumed => { + "that code has already been used — codes are single-use" + } RedeemError::RateLimited => { "too many redemption attempts from this machine in the last hour" } @@ -19891,14 +20264,18 @@ fn cmd_access(action: AccessCmd) -> i32 { if !rule.surfaces.is_empty() || rule.origin != spt_store::access::OriginQualifier::Any { - eprintln!("ACCESS_ALLOW_SCOPE:{endpoint}:{node} — {}", describe_rule(&rule)); + eprintln!( + "ACCESS_ALLOW_SCOPE:{endpoint}:{node} — {}", + describe_rule(&rule) + ); } // Read AFTER the save, from the store that now holds this rule: // the question is what the chain says now, not what it said // before the write the operator is being told about. - if let Some(line) = - discover_still_open_line(&endpoint, node_still_sees_endpoint(&s, &endpoint, &node)) - { + if let Some(line) = discover_still_open_line( + &endpoint, + node_still_sees_endpoint(&s, &endpoint, &node), + ) { eprintln!("{line}"); } } @@ -19980,10 +20357,8 @@ fn access_endpoint_directory() -> crate::accessview::EndpointDirectory { continue; }; for row in resource_projection(reg, |_| false) { - let display = spt_net::net::registry::node_label_display( - &row.node, - row.node_label.as_deref(), - ); + let display = + spt_net::net::registry::node_label_display(&row.node, row.node_label.as_deref()); let entry = dir .entry(row.endpoint_id.clone()) .or_insert_with(|| (display, Vec::new())); @@ -20093,8 +20468,7 @@ fn cmd_access_view( let rows = spt_store::briefing::ruleset_rows_where_with( &store, |scope, rule| { - drill.matches(&rule.subject) - && target.is_none_or(|t| scope == t || scope == "node") + drill.matches(&rule.subject) && target.is_none_or(|t| scope == t || scope == "node") }, |hex| roster_labels(hex).or_else(|| crate::api::reporting::resolve_node_label(hex)), ); @@ -20154,13 +20528,8 @@ fn cmd_access_view( return 0; } for acl in targets { - let items = crate::accessview::roster_for_target( - acl, - &store.node.modes, - &captured, - &home, - &dir, - ); + let items = + crate::accessview::roster_for_target(acl, &store.node.modes, &captured, &home, &dir); print!( "{}", crate::accessview::render_roster( @@ -20185,8 +20554,7 @@ fn cmd_daemon_access(json: bool) -> i32 { .iter() .map(|c| (c.subnet.clone(), c.modes.clone())) .collect(); - let items = - crate::accessview::roster_for_node(&store.node, &captured, &node_ident_display()); + let items = crate::accessview::roster_for_node(&store.node, &captured, &node_ident_display()); if json { return print_json(&items); } @@ -20296,7 +20664,11 @@ fn adapter_update_install_dir(record: &spt_runtime::registry::AdapterRecord) -> fn subprocess_detail(stderr: &str, stdout: &str) -> String { let detail = { let e = stderr.trim(); - if e.is_empty() { stdout.trim() } else { e } + if e.is_empty() { + stdout.trim() + } else { + e + } }; if detail.is_empty() { String::new() @@ -20373,7 +20745,9 @@ fn cmd_adapter(action: AdapterCmd, json: bool) -> i32 { _ => None, } { if let Some(rec) = registered_github_home(&adapters, spec) { - let dir = adapters.join("_github").join(spec.replace(['/', '\\'], "-")); + let dir = adapters + .join("_github") + .join(spec.replace(['/', '\\'], "-")); eprintln!( "ADAPTER_ADD_ALREADY_REGISTERED:{}: already installed at {}.\n\ Use `spt adapter update {}` to refresh it in place (safe stage-then-swap),\n\ @@ -20422,7 +20796,10 @@ fn cmd_adapter(action: AdapterCmd, json: bool) -> i32 { if dest.exists() { if let Err(e) = std::fs::remove_dir_all(&dest) { let _ = std::fs::remove_dir_all(&staging); - eprintln!("ADAPTER_CLONE_FAIL: replace {}: {e}", dest.display()); + eprintln!( + "ADAPTER_CLONE_FAIL: replace {}: {e}", + dest.display() + ); return 1; } } @@ -20447,15 +20824,14 @@ fn cmd_adapter(action: AdapterCmd, json: bool) -> i32 { } (None, None, Some(spec)) => { let asset = asset.as_deref().unwrap_or("adapter.spt"); - match fetch_release_adapter(&adapters, &spec, tag.as_deref(), asset, transport) { + match fetch_release_adapter(&adapters, &spec, tag.as_deref(), asset, transport) + { Ok(dest) => dest, Err(code) => return code, } } _ => { - eprintln!( - "ADAPTER_BAD_ARGS: exactly one of , --github, or --release" - ); + eprintln!("ADAPTER_BAD_ARGS: exactly one of , --github, or --release"); return 2; } }; @@ -20507,7 +20883,11 @@ fn cmd_adapter(action: AdapterCmd, json: bool) -> i32 { spt_daemon::adapter_update::AdapterUpdateOutcome::Delegate(cmd) => { let rc = conduct("INSTALL", &cmd); // Only run the post-step once the acquisition succeeded. - if rc == 0 { install_post_step() } else { rc } + if rc == 0 { + install_post_step() + } else { + rc + } } spt_daemon::adapter_update::AdapterUpdateOutcome::Skipped(reason) => { // file_pull with no payload yet: the install is GENUINELY @@ -20662,51 +21042,60 @@ fn cmd_adapter(action: AdapterCmd, json: bool) -> i32 { AdapterCmd::Version { option } => cmd_adapter_version(&adapters, &option, json), // [impl->REQ-SHELL-HINTS] AdapterCmd::Hints { option } => cmd_adapter_hints(&adapters, &option, json), - AdapterCmd::GetString { option, key } => match registry::get_string(&adapters, &option, &key) - { - Ok(Some(value)) => { - // Strings print raw; structured leaves print as JSON (machine- - // readable for a hook). spt-core never executes the value. - if let Some(s) = value.as_str() { - println!("{s}"); - } else { - println!("{}", serde_json::to_string(&value).unwrap_or_default()); + AdapterCmd::GetString { option, key } => { + match registry::get_string(&adapters, &option, &key) { + Ok(Some(value)) => { + // Strings print raw; structured leaves print as JSON (machine- + // readable for a hook). spt-core never executes the value. + if let Some(s) = value.as_str() { + println!("{s}"); + } else { + println!("{}", serde_json::to_string(&value).unwrap_or_default()); + } + 0 + } + Ok(None) => { + eprintln!("ADAPTER_STRING_UNSET:{option}: no value at '{key}'"); + 1 + } + Err(e) => { + eprintln!("ADAPTER_STRING_FAIL:{option}: {e}"); + 1 } - 0 - } - Ok(None) => { - eprintln!("ADAPTER_STRING_UNSET:{option}: no value at '{key}'"); - 1 - } - Err(e) => { - eprintln!("ADAPTER_STRING_FAIL:{option}: {e}"); - 1 } - }, + } // [impl->REQ-TERM-5] // [impl->REQ-ADAPTER-PROOF-DIR-OVERRIDE] - AdapterCmd::DigestProof { option, sample, session, dir, manifest } => { - cmd_adapter_digest_proof( - &adapters, - &option, - sample.as_deref(), - session.as_deref(), - dir.as_deref(), - manifest.as_deref(), - ) - } + AdapterCmd::DigestProof { + option, + sample, + session, + dir, + manifest, + } => cmd_adapter_digest_proof( + &adapters, + &option, + sample.as_deref(), + session.as_deref(), + dir.as_deref(), + manifest.as_deref(), + ), // [impl->REQ-ADAPTER-TRANSLATE-PROOF] // [impl->REQ-ADAPTER-PROOF-DIR-OVERRIDE] - AdapterCmd::TranslateProof { option, event, session, dir, manifest } => { - cmd_adapter_translate_proof( - &adapters, - &option, - &event, - session.as_deref(), - dir.as_deref(), - manifest.as_deref(), - ) - } + AdapterCmd::TranslateProof { + option, + event, + session, + dir, + manifest, + } => cmd_adapter_translate_proof( + &adapters, + &option, + &event, + session.as_deref(), + dir.as_deref(), + manifest.as_deref(), + ), // [impl->REQ-MANIFEST-3] AdapterCmd::SetString { option, key, value } => { let (adapter, profile) = spt_runtime::profile::split_option(&option); @@ -20751,7 +21140,10 @@ fn cmd_adapter(action: AdapterCmd, json: bool) -> i32 { } else { match spt_runtime::resolve::set_active(&adapters, &target) { Ok(keys) => { - println!("{target} is now the active profile for: {}.", keys.join(", ")); + println!( + "{target} is now the active profile for: {}.", + keys.join(", ") + ); 0 } Err(e) => { @@ -20775,10 +21167,7 @@ fn cmd_adapter(action: AdapterCmd, json: bool) -> i32 { /// (adapter file deletions are rare; a stale unreferenced file is harmless), so a /// running binary that vanished from the manifest is never yanked mid-update. // [impl->REQ-ADAPTER-LIVE-UPDATE] -fn apply_release_crc_swap( - staged: &std::path::Path, - dest: &std::path::Path, -) -> Result<(), String> { +fn apply_release_crc_swap(staged: &std::path::Path, dest: &std::path::Path) -> Result<(), String> { // Extract to a sibling temp tree (platform-selective per W1), then diff+swap // into `dest`. The temp tree is removed on every exit. let staging = dest.with_extension("crc-stage"); @@ -20786,7 +21175,8 @@ fn apply_release_crc_swap( std::fs::create_dir_all(&staging).map_err(|e| e.to_string())?; let result = (|| { extract_release_archive(staged, &staging).map_err(|e| e.to_string())?; - let plan = spt_daemon::crc_swap::plan_crc_swap(&staging, dest).map_err(|e| e.to_string())?; + let plan = + spt_daemon::crc_swap::plan_crc_swap(&staging, dest).map_err(|e| e.to_string())?; spt_daemon::crc_swap::apply_crc_swap(&plan).map_err(|e| e.to_string()) })(); let _ = std::fs::remove_dir_all(&staging); @@ -20950,7 +21340,8 @@ fn staged_floor_ok( let peek = dest.with_extension("floor-peek"); let _ = std::fs::remove_dir_all(&peek); let res = (|| -> Result<(), String> { - std::fs::create_dir_all(&peek).map_err(|e| format!("could not verify the core-version floor: {e}"))?; + std::fs::create_dir_all(&peek) + .map_err(|e| format!("could not verify the core-version floor: {e}"))?; extract_release_archive(staged, &peek) .map_err(|e| format!("could not verify the core-version floor: {e}"))?; let mtoml = std::fs::read_to_string(peek.join("manifest.toml")) @@ -21051,7 +21442,9 @@ fn nudge_adapter_service(manifest: &spt_runtime::manifest::Manifest, adapter: &s let what = match o.outcome { ServiceOutcome::Started => "started".to_string(), ServiceOutcome::AlreadyRunning => "already running".to_string(), - ServiceOutcome::Held => "held for an update — starts when the hold releases".to_string(), + ServiceOutcome::Held => { + "held for an update — starts when the hold releases".to_string() + } ServiceOutcome::BindDeferred => { "start = \"bind\" — starts at the adapter's first shell bind".to_string() } @@ -21195,8 +21588,10 @@ fn cmd_adapter_service(action: AdapterServiceCmd, json: bool) -> i32 { } if let Some(o) = asked.as_deref() { if rows.is_empty() { - eprintln!("ADAPTER_SERVICE_UNKNOWN:{o}: no registered adapter declares a service for \ - this option, and none is supervised"); + eprintln!( + "ADAPTER_SERVICE_UNKNOWN:{o}: no registered adapter declares a service for \ + this option, and none is supervised" + ); return 1; } } else if rows.is_empty() { @@ -21259,7 +21654,10 @@ fn apply_release_via_daemon( /// trailing-trimmed (the caller adds one newline). Pure (modulo `color`); the /// caller invokes it ONLY after an update is actually applied — never on a no-op. // [impl->REQ-ADAPTER-UPDATE-MESSAGE] -fn adapter_update_notice(manifest: &spt_runtime::manifest::Manifest, color: bool) -> Option { +fn adapter_update_notice( + manifest: &spt_runtime::manifest::Manifest, + color: bool, +) -> Option { let msg = manifest.update.as_ref()?.message.as_deref()?; Some(crate::helpfmt::render(msg, color).trim_end().to_string()) } @@ -21631,7 +22029,10 @@ fn update_one_adapter( None => { // Validation requires `repo`; a record reaching here without one // is corrupt — never silently fetch from nowhere. - eprintln!("ADAPTER_UPDATE_FAIL:{}: gh_release missing repo", record.name); + eprintln!( + "ADAPTER_UPDATE_FAIL:{}: gh_release missing repo", + record.name + ); return AdapterUpdateOutcome::Failed; } }; @@ -21752,8 +22153,8 @@ fn update_one_adapter( // though: a daemon that is not running is supervising nothing, so // there is nothing to quiesce and the direct swap is correct. // [impl->REQ-RESIDENT-SERVICE] - let service_needs_daemon = effective_manifest.service.is_some() - && spt_daemon::is_running(); + let service_needs_daemon = + effective_manifest.service.is_some() && spt_daemon::is_running(); let applied = if adapter_has_live_endpoint(&record.name) || service_needs_daemon { eprintln!( "ADAPTER_UPDATE_LIVE:{}: live endpoint(s) or a supervised service — \ @@ -21847,10 +22248,7 @@ fn update_one_adapter( /// --jq .tag_name` (the private-repo path). (REQ-UPD-9, REQ-ADAPTER-GH-TRANSPORT) // [impl->REQ-UPD-9] // [impl->REQ-ADAPTER-GH-TRANSPORT] -fn gh_latest_release_version( - repo: &str, - transport: EffectiveTransport, -) -> Result { +fn gh_latest_release_version(repo: &str, transport: EffectiveTransport) -> Result { // Test seam: `SPT_TEST_GH_LATEST` short-circuits the network so the // `adapter update` post-step flow (REQ-ADAPTER-UPDATE-POST) can be integration- // tested deterministically — set it to the installed version to exercise the @@ -21872,12 +22270,8 @@ fn gh_latest_release_version( } EffectiveTransport::Gh => { let (template, keys) = gh_version_command(repo); - match spt_runtime::run_bounded_command( - &template, - &keys, - Duration::from_secs(60), - None, - ) { + match spt_runtime::run_bounded_command(&template, &keys, Duration::from_secs(60), None) + { Ok(out) if out.success() => out.stdout.trim().to_string(), Ok(out) => return Err(format!("gh api exit {:?}", out.status_code)), Err(e) => return Err(e.to_string()), @@ -21956,8 +22350,13 @@ fn verify_staged_archive( let bytes = std::fs::read(staged).map_err(|e| e.to_string())?; let tag_v = format!("v{tag}"); let github = adapters.join("_github"); - let sig_bytes = - fetch_release_asset_bytes(repo, Some(&tag_v), &format!("{asset}.sig"), transport, &github)?; + let sig_bytes = fetch_release_asset_bytes( + repo, + Some(&tag_v), + &format!("{asset}.sig"), + transport, + &github, + )?; let sig_hex = String::from_utf8(sig_bytes).map_err(|e| e.to_string())?; spt_daemon::verify_detached(&bytes, sig_hex.trim(), &key).map_err(|e| e.to_string()) } @@ -22096,13 +22495,14 @@ fn cmd_adapter_digest_proof( // bare program there before PATH so proof runs exactly as the daemon does // (REQ-INSTALL-11). Registered adapter → its `source_dir`; with // `--dir`/`--manifest` → an on-disk DEV install (REQ-ADAPTER-PROOF-DIR-OVERRIDE). - let (install_dir, manifest) = match resolve_proof_target(adapters, option, dir, manifest_override) { - Ok(pair) => pair, - Err(e) => { - eprintln!("DIGEST_PROOF_FAIL:{option}: {e}"); - return 1; - } - }; + let (install_dir, manifest) = + match resolve_proof_target(adapters, option, dir, manifest_override) { + Ok(pair) => pair, + Err(e) => { + eprintln!("DIGEST_PROOF_FAIL:{option}: {e}"); + return 1; + } + }; let Some(declared) = manifest.digest.clone() else { eprintln!("DIGEST_PROOF_NO_SECTION:{option}: adapter declares no [digest] extractor"); return 2; @@ -22166,12 +22566,17 @@ fn cmd_adapter_digest_proof( } }; - let config = spt_daemon::resolve_config(Some(&declared), &spt_daemon::DigestOverride::default()); + let config = + spt_daemon::resolve_config(Some(&declared), &spt_daemon::DigestOverride::default()); let (digest, diag) = spt_term::project_lines_diagnosed(lines.iter().map(String::as_str), &config); println!("=== digest-proof: {option} ==="); - println!("parsed {} record(s), dropped {}", diag.parsed, diag.drop_count()); + println!( + "parsed {} record(s), dropped {}", + diag.parsed, + diag.drop_count() + ); println!("\n--- parsed records ---"); for l in &lines { if spt_term::record_to_tagged_result(l).is_ok() { @@ -22194,7 +22599,10 @@ fn cmd_adapter_digest_proof( // A broken extractor (drops) or a silent empty (nothing parsed) fails the proof. if diag.drop_count() > 0 { - eprintln!("DIGEST_PROOF_DROPS:{option}: {} line(s) did not match the contract", diag.drop_count()); + eprintln!( + "DIGEST_PROOF_DROPS:{option}: {} line(s) did not match the contract", + diag.drop_count() + ); return 1; } if diag.parsed == 0 { @@ -22247,13 +22655,14 @@ fn cmd_adapter_translate_proof( // does (REQ-INSTALL-11), mirroring the daemon's harnesshost path resolution. // Registered adapter → its `source_dir`; with `--dir`/`--manifest` → an on-disk // DEV install (REQ-ADAPTER-PROOF-DIR-OVERRIDE). - let (install_dir, manifest) = match resolve_proof_target(adapters, option, dir, manifest_override) { - Ok(pair) => pair, - Err(e) => { - eprintln!("TRANSLATE_PROOF_FAIL:{option}: {e}"); - return 1; - } - }; + let (install_dir, manifest) = + match resolve_proof_target(adapters, option, dir, manifest_override) { + Ok(pair) => pair, + Err(e) => { + eprintln!("TRANSLATE_PROOF_FAIL:{option}: {e}"); + return 1; + } + }; let Some(declared) = manifest.message_idle_translation_binary.clone() else { eprintln!( "TRANSLATE_PROOF_NO_SECTION:{option}: adapter declares no \ @@ -22528,8 +22937,13 @@ fn cmd_shell(action: ShellCmd, json: bool) -> i32 { // not the parent. Deregistered/harness adapters and unknown profiles // refuse. Approval/cap gates extend here at D3d. let adapters_dir = spt_store::perch::adapters_dir(); - let shell_manifest = match spt_runtime::registry::resolve_option(&adapters_dir, &adapter) { - Ok((_, m)) if m.adapter.kind == spt_runtime::manifest::AdapterKind::Shell => m.shell, + let shell_manifest = match spt_runtime::registry::resolve_option( + &adapters_dir, + &adapter, + ) { + Ok((_, m)) if m.adapter.kind == spt_runtime::manifest::AdapterKind::Shell => { + m.shell + } Ok(_) => None, // a harness adapter has no [shell] Err(e) => { eprintln!( @@ -22583,7 +22997,9 @@ fn cmd_shell(action: ShellCmd, json: bool) -> i32 { let parent = spt_runtime::profile::split_option(&adapter).0; let existing = shellinfo::list_shells(&owlery, &owner) .iter() - .filter(|(_, i)| spt_runtime::profile::split_option(&i.adapter_name).0 == parent) + .filter(|(_, i)| { + spt_runtime::profile::split_option(&i.adapter_name).0 == parent + }) .count(); if existing >= cap as usize { match shell_manifest.over_cap { @@ -22802,10 +23218,13 @@ fn cmd_shell(action: ShellCmd, json: bool) -> i32 { // adapter_name → overlaid [shell]); a deregistered parent yields // None and close falls back to the manifestless force path. let adapters_dir = spt_store::perch::adapters_dir(); - let shell = spt_runtime::registry::resolve_option(&adapters_dir, &info.adapter_name) - .ok() - .filter(|(_, m)| m.adapter.kind == spt_runtime::manifest::AdapterKind::Shell) - .and_then(|(_, m)| m.shell); + let shell = + spt_runtime::registry::resolve_option(&adapters_dir, &info.adapter_name) + .ok() + .filter(|(_, m)| { + m.adapter.kind == spt_runtime::manifest::AdapterKind::Shell + }) + .and_then(|(_, m)| m.shell); match spt_daemon::shellhost::close_shell(&owlery, &owner, &id, shell.as_ref()) { Ok(spt_daemon::shellhost::CloseOutcome::TornDown) => { spt_daemon::grants::revoke_can_shutdown_grant(&id); @@ -22962,8 +23381,13 @@ fn cmd_shell(action: ShellCmd, json: bool) -> i32 { eprintln!("SHELL_DRIVE_FAIL: daemon start: {e}"); return 1; } - match spt_daemon::drive_channel_write(&owlery, &owner, &shell_ref, &drive_type, &payload) - { + match spt_daemon::drive_channel_write( + &owlery, + &owner, + &shell_ref, + &drive_type, + &payload, + ) { Ok(spt_daemon::DriveDelivery::Driven { id, drive_type }) => { eprintln!("SHELL_DRIVEN:{id} type={drive_type} (latest-wins slot; drains via api drive-poll --link)"); 0 @@ -23466,7 +23890,10 @@ fn escalate_act( } else { "[o]nce / [d]eny" }; - eprintln!("SHELL_ACT_APPROVAL:{}: {why} (class {class}) — approve? {menu}", ask.capability); + eprintln!( + "SHELL_ACT_APPROVAL:{}: {why} (class {class}) — approve? {menu}", + ask.capability + ); let mut line = String::new(); let _ = std::io::stdin().read_line(&mut line); let mut store = spt_store::grants::GrantStore::load(); @@ -23765,7 +24192,9 @@ pub(crate) enum PurgeOutcome { /// class: acting on a claim we have just been told is false. Distinct from /// the ordinary non-quiesce case below, which keeps the clean-anyway /// posture — a slow-to-settle endpoint is not a named survivor. - RefusedSurvivor { root_pid: Option }, + RefusedSurvivor { + root_pid: Option, + }, /// The caller's confirm declined. Aborted, /// Everything else was cleaned but the perch tree survived (the one hard @@ -23919,7 +24348,9 @@ fn ceremony_agent_ground() -> Option { /// found. All gating lives in [`decide_ceremony`]. // [impl->REQ-ER-CEREMONY-VERB] fn cmd_endpoint_engine_room(subnet: &str, adapter: &str) -> i32 { - let subnet_joined = spt_store::subnet::SubnetStore::load().find(subnet).is_some(); + let subnet_joined = spt_store::subnet::SubnetStore::load() + .find(subnet) + .is_some(); let adapter_registered = spt_runtime::registry::registered(&spt_store::perch::adapters_dir()) .iter() .any(|(rec, _)| rec.active && rec.name == adapter); @@ -24081,7 +24512,10 @@ pub(crate) fn purge_endpoint_core_with( // Self-guard: never purge the endpoint THIS session is running as (the harness // injects SPT_ENDPOINT_ID = the id) — that would delete your own records mid-run. if std::env::var("SPT_ENDPOINT_ID").ok().as_deref() == Some(id) { - return PurgeReport { outcome: PurgeOutcome::RefusedOwnEndpoint, warnings }; + return PurgeReport { + outcome: PurgeOutcome::RefusedOwnEndpoint, + warnings, + }; } let perch = perch::resolve_perch_path(id, ParentHint::Infer); @@ -24091,7 +24525,10 @@ pub(crate) fn purge_endpoint_core_with( // never ask a question it is going to decline anyway. let was_alive = spt_store::liveness::is_perch_alive(&perch); if was_alive && !force { - return PurgeReport { outcome: PurgeOutcome::RefusedOnline, warnings }; + return PurgeReport { + outcome: PurgeOutcome::RefusedOnline, + warnings, + }; } // Confirm (destructive + irreversible) — the CALLER owns the surface. @@ -24100,7 +24537,10 @@ pub(crate) fn purge_endpoint_core_with( // to. Declining returns Aborted with genuinely nothing done. // [impl->REQ-ENDPOINT-TEARDOWN-AUTHORITY] if !confirm() { - return PurgeReport { outcome: PurgeOutcome::Aborted, warnings }; + return PurgeReport { + outcome: PurgeOutcome::Aborted, + warnings, + }; } if was_alive { @@ -24233,9 +24673,15 @@ pub(crate) fn purge_endpoint_core_with( if let Err(e) = spt_store::engineroom::clear() { warnings.push(format!("WARN: engine-room binding not cleared: {e}")); } - return PurgeReport { outcome: PurgeOutcome::EngineRoomReset, warnings }; + return PurgeReport { + outcome: PurgeOutcome::EngineRoomReset, + warnings, + }; + } + PurgeReport { + outcome: PurgeOutcome::Purged, + warnings, } - PurgeReport { outcome: PurgeOutcome::Purged, warnings } } // [impl->REQ-ENDPOINT-PURGE] @@ -24459,7 +24905,11 @@ pub(crate) fn cmd_endpoint_gc(reap: bool, json: bool) -> i32 { .collect::>(), }); println!("{out}"); - return if report.reap_failures.is_empty() { 0 } else { 1 }; + return if report.reap_failures.is_empty() { + 0 + } else { + 1 + }; } print!("{}", render_gc_report(&report, reap)); @@ -24779,8 +25229,14 @@ mod tests { ) .expect_err("RC_ATTACH carries no sender stamp"); assert!(err.contains("ACCESS_DEAD_SUBJECT"), "{err}"); - assert!(err.contains("RC_ATTACH"), "names the offending surface: {err}"); - assert!(err.contains("--node"), "and the way to say it instead: {err}"); + assert!( + err.contains("RC_ATTACH"), + "names the offending surface: {err}" + ); + assert!( + err.contains("--node"), + "and the way to say it instead: {err}" + ); // MSG is attributable today, so the same rule there is fine — this is // read from the surface table, so XFER flipping later needs no edit @@ -24850,7 +25306,9 @@ mod tests { None, None, ) - .expect("a bare endpoint id on an attributable surface is exactly what this surface is for"); + .expect( + "a bare endpoint id on an attributable surface is exactly what this surface is for", + ); } // [unit->REQ-ACL-RULE-MUTATION] the malformed shapes each refuse with a @@ -24859,11 +25317,20 @@ mod tests { fn malformed_tuple_flags_refuse_with_a_usable_diagnostic() { use spt_store::access::RuleDecision; - let no_subject = - build_access_rule(RuleDecision::Allow, Some("MSG".into()), None, None, None, None) - .expect_err("a rule must be about someone"); + let no_subject = build_access_rule( + RuleDecision::Allow, + Some("MSG".into()), + None, + None, + None, + None, + ) + .expect_err("a rule must be about someone"); assert!(no_subject.contains("ACCESS_NO_SUBJECT"), "{no_subject}"); - assert!(no_subject.contains("--any-of"), "lists the options: {no_subject}"); + assert!( + no_subject.contains("--any-of"), + "lists the options: {no_subject}" + ); let short_hex = build_access_rule( RuleDecision::Allow, @@ -24886,7 +25353,10 @@ mod tests { ) .expect_err("origin is a closed vocabulary"); assert!(bad_origin.contains("ACCESS_BAD_ORIGIN"), "{bad_origin}"); - assert!(bad_origin.contains("user"), "names the valid words: {bad_origin}"); + assert!( + bad_origin.contains("user"), + "names the valid words: {bad_origin}" + ); } // [unit->REQ-ACL-INTRA-NODE-SELF] THE `--node` SPELLING TABLE, written out @@ -24922,8 +25392,7 @@ mod tests { // 3. `self` with NO identity REFUSES rather than minting one. Writing a // rule must not create the identity that rule is about. - let unprovisioned = - resolve_node_subject("self", None, none).expect_err("nothing to name"); + let unprovisioned = resolve_node_subject("self", None, none).expect_err("nothing to name"); assert!( unprovisioned.contains("ACCESS_NO_NODE_IDENTITY"), "{unprovisioned}" @@ -24950,7 +25419,10 @@ mod tests { // 5. An unknown name refuses and TEACHES the three spellings. let unknown = resolve_node_subject("ghost", Some(&me), none).expect_err("unknown"); assert!(unknown.contains("ACCESS_UNKNOWN_NODE"), "{unknown}"); - assert!(unknown.contains("self"), "names the reserved word: {unknown}"); + assert!( + unknown.contains("self"), + "names the reserved word: {unknown}" + ); // 6. AN AMBIGUOUS NAME REFUSES WITH THE CANDIDATES rather than picking. // A label is a LEASE — two machines can hold one — so a resolver that @@ -24958,7 +25430,10 @@ mod tests { let twins = |_: &str| vec![me.clone(), peer.clone()]; let ambiguous = resolve_node_subject("twin", Some(&me), twins).expect_err("two nodes"); assert!(ambiguous.contains("ACCESS_AMBIGUOUS_NODE"), "{ambiguous}"); - assert!(ambiguous.contains(&me) && ambiguous.contains(&peer), "{ambiguous}"); + assert!( + ambiguous.contains(&me) && ambiguous.contains(&peer), + "{ambiguous}" + ); // 7. THE RESERVED WORD OUTRANKS THE DIRECTORY. A node labelled `self` // must not shadow the spelling every own-node rule is written with. @@ -25035,7 +25510,9 @@ mod tests { // hides a dropped flag. #[test] fn the_positional_allow_spelling_carries_its_flags_into_the_rule() { - use spt_store::access::{MutationOp, MutationScope, OriginQualifier, RuleDecision, Subject}; + use spt_store::access::{ + MutationOp, MutationScope, OriginQualifier, RuleDecision, Subject, + }; /// One row: what the operator typed, and what must be on the rule. struct Arm { @@ -25210,7 +25687,10 @@ mod tests { decision: RuleDecision::Deny, }; let said = describe_rule(&denied_human); - assert!(said.contains("may NOT reach"), "the polarity is loud: {said}"); + assert!( + said.contains("may NOT reach"), + "the polarity is loud: {said}" + ); assert!(said.contains("every surface"), "{said}"); assert!(said.contains("human callers only"), "{said}"); } @@ -25223,7 +25703,10 @@ mod tests { // No label / empty label → bare `cli`, no trailing separator. assert_eq!(cli_origin_from_label(None), "cli"); assert_eq!(cli_origin_from_label(Some("")), "cli"); - assert!(!cli_origin_from_label(None).ends_with('@'), "never a dangling cli@"); + assert!( + !cli_origin_from_label(None).ends_with('@'), + "never a dangling cli@" + ); // The live resolver is never blank and never a dangling @ (label or bare cli). let live = cli_origin_label(); assert!(!live.is_empty() && !live.ends_with('@')); @@ -25243,13 +25726,34 @@ mod tests { "no source knows this id — the ONLY shape that may be refused" ); let shapes: [(&str, StopEvidence); 4] = [ - ("ready marker", StopEvidence { ready_marker: true, ..Default::default() }), - ("perch record", StopEvidence { perch_record: true, ..Default::default() }), + ( + "ready marker", + StopEvidence { + ready_marker: true, + ..Default::default() + }, + ), + ( + "perch record", + StopEvidence { + perch_record: true, + ..Default::default() + }, + ), ( "registered address", - StopEvidence { registered_address: true, ..Default::default() }, + StopEvidence { + registered_address: true, + ..Default::default() + }, + ), + ( + "broker row", + StopEvidence { + broker_row: true, + ..Default::default() + }, ), - ("broker row", StopEvidence { broker_row: true, ..Default::default() }), ]; for (name, evidence) in shapes { assert!( @@ -25270,7 +25774,11 @@ mod tests { // Nothing at all: every source empty, and the broker (asked, because // nothing local answered) has no row either. let none = resolve_stop_evidence_in(owlery, "ghost", || false); - assert_eq!(none, StopEvidence::default(), "an unknown id leaves no trace anywhere"); + assert_eq!( + none, + StopEvidence::default(), + "an unknown id leaves no trace anywhere" + ); assert!(!none.known()); // A perch record alone — the shape a stopped-but-not-purged endpoint @@ -25279,7 +25787,10 @@ mod tests { std::fs::create_dir_all(owlery.join("recorded")).unwrap(); let record_only = resolve_stop_evidence_in(owlery, "recorded", || false); assert!(record_only.perch_record && !record_only.ready_marker); - assert!(record_only.known(), "a record-only endpoint is still stoppable"); + assert!( + record_only.known(), + "a record-only endpoint is still stoppable" + ); // Its ready marker joins it (a marker lives INSIDE the perch dir, so // "ready without a record" is not a shape the filesystem can express — @@ -25293,13 +25804,19 @@ mod tests { registry::register_address("registered", &addr, owlery).unwrap(); let address_only = resolve_stop_evidence_in(owlery, "registered", || false); assert!(address_only.registered_address && !address_only.perch_record); - assert!(address_only.known(), "a registry row alone is still stoppable"); + assert!( + address_only.known(), + "a registry row alone is still stoppable" + ); // A broker row alone: nothing local, so the probe IS consulted. let broker_only = resolve_stop_evidence_in(owlery, "hosted", || true); assert_eq!( broker_only, - StopEvidence { broker_row: true, ..Default::default() }, + StopEvidence { + broker_row: true, + ..Default::default() + }, "the broker answered where the disk could not" ); assert!(broker_only.known()); @@ -25428,11 +25945,17 @@ mod tests { fn update_fetch_apply_flag_parses() { assert!(matches!( parse(&["spt", "update", "fetch", "--apply"]).unwrap().cmd, - Some(Cmd::Update { action: Some(UpdateCmd::Fetch { apply: true, .. }), .. }) + Some(Cmd::Update { + action: Some(UpdateCmd::Fetch { apply: true, .. }), + .. + }) )); assert!(matches!( parse(&["spt", "update", "fetch"]).unwrap().cmd, - Some(Cmd::Update { action: Some(UpdateCmd::Fetch { apply: false, .. }), .. }) + Some(Cmd::Update { + action: Some(UpdateCmd::Fetch { apply: false, .. }), + .. + }) )); } @@ -25586,7 +26109,11 @@ mod tests { }, ), ]; - assert_eq!(adapter_update_exit(&applied), 0, "nothing declined, nothing broke"); + assert_eq!( + adapter_update_exit(&applied), + 0, + "nothing declined, nothing broke" + ); assert_eq!( adapter_update_exit(&[refused("omp-spt")]), @@ -25595,7 +26122,10 @@ mod tests { roll records itself as rolled on a node it never touched" ); - let mixed = vec![refused("omp-spt"), ("dd".to_string(), AdapterUpdateOutcome::Failed)]; + let mixed = vec![ + refused("omp-spt"), + ("dd".to_string(), AdapterUpdateOutcome::Failed), + ]; assert_eq!( adapter_update_exit(&mixed), 1, @@ -25603,7 +26133,10 @@ mod tests { mask it" ); - let refused_and_fine = vec![refused("omp-spt"), ("dd".to_string(), AdapterUpdateOutcome::SkippedLocal)]; + let refused_and_fine = vec![ + refused("omp-spt"), + ("dd".to_string(), AdapterUpdateOutcome::SkippedLocal), + ]; assert_eq!( adapter_update_exit(&refused_and_fine), EXIT_REFUSED_NO_WORK, @@ -25680,7 +26213,7 @@ mod tests { // composite (no subcommand), with `--core-only`/`-c` and `--restart` flags; // flags conflict with subcommands (clap-level). #[test] - fn bare_update_parses_composite_flags() { + fn bare_update_parses_composite_flags() { match parse(&["spt", "update"]).unwrap().cmd { Some(Cmd::Update { action: None, @@ -25771,16 +26304,31 @@ mod tests { // outranks anything. #[test] fn the_fold_is_total_and_classes_by_value() { - assert_eq!(fold_composite_exit(EXIT_REFUSED_NO_WORK, 42), 42, "unknown nonzero = failure"); - assert_eq!(fold_composite_exit(EXIT_REFUSED_NO_WORK, 2), 2, "usage code = failure"); + assert_eq!( + fold_composite_exit(EXIT_REFUSED_NO_WORK, 42), + 42, + "unknown nonzero = failure" + ); + assert_eq!( + fold_composite_exit(EXIT_REFUSED_NO_WORK, 2), + 2, + "usage code = failure" + ); assert_eq!( fold_composite_exit(EXIT_NOT_ELEVATED, EXIT_REFUSED_NO_WORK), EXIT_NOT_ELEVATED, "the two distinct 3s are ONE class — a fold that cared which const minted it would grow a second vocabulary to drift from" ); assert_eq!(fold_composite_exit(0, 0), 0); - assert_eq!(fold_composite_exit(1, 0), 1, "a later success never clears a failure"); - assert_eq!(fold_composite_exit(EXIT_REFUSED_NO_WORK, 0), EXIT_REFUSED_NO_WORK); + assert_eq!( + fold_composite_exit(1, 0), + 1, + "a later success never clears a failure" + ); + assert_eq!( + fold_composite_exit(EXIT_REFUSED_NO_WORK, 0), + EXIT_REFUSED_NO_WORK + ); } // [unit->REQ-UPDATE-COMPOSITE-EXIT-PRECEDENCE] FIRST-SEEN SURVIVES within a @@ -25788,7 +26336,11 @@ mod tests { // already read, and later-overwrites-earlier is the defect mechanism itself. #[test] fn within_a_class_the_first_code_survives() { - assert_eq!(fold_composite_exit(1, 42), 1, "a second failure does not overwrite the first"); + assert_eq!( + fold_composite_exit(1, 42), + 1, + "a second failure does not overwrite the first" + ); assert_eq!( fold_composite_exit(EXIT_NOT_ELEVATED, EXIT_REFUSED_NO_WORK), EXIT_NOT_ELEVATED, @@ -25815,7 +26367,10 @@ mod tests { !plan_update_legs(false, false).contains(&UpdateLeg::Finish), "the plain plan ends at Adapters, which is why the face is unreachable there" ); - assert!(!composite_abort_on_failure(UpdateLeg::Adapters), "and the adapters failure is the one that must SURVIVE to be masked"); + assert!( + !composite_abort_on_failure(UpdateLeg::Adapters), + "and the adapters failure is the one that must SURVIVE to be masked" + ); } // [unit->REQ-UPDATE-RESTART-SAFE-SWAP] lethal-leg-LAST: `--restart` plans @@ -25941,7 +26496,10 @@ mod tests { notice, "Reload required: run /reload-plugins.", "color-off render strips the markdown markers to bare prose", ); - assert!(!notice.contains('*'), "no literal markdown markers leak through"); + assert!( + !notice.contains('*'), + "no literal markdown markers leak through" + ); } // [unit->REQ-ADAPTER-UPDATE-MESSAGE] No `[update].message` ⇒ no notice: an @@ -25963,7 +26521,11 @@ mod tests { #[test] fn post_step_notice_arbitration() { assert_eq!(post_step_notice(""), PostNotice::None); - assert_eq!(post_step_notice(" \n "), PostNotice::None, "blank → None"); + assert_eq!( + post_step_notice(" \n "), + PostNotice::None, + "blank → None" + ); assert_eq!( post_step_notice(UPDATE_POST_MESSAGE_SENTINEL), PostNotice::ManifestMessage, @@ -26009,12 +26571,19 @@ mod tests { let (idir, m) = resolve_proof_target(&adapters, "dev", Some(devdir.to_str().unwrap()), None).unwrap(); assert_eq!(idir, devdir, "--dir sets the install dir"); - assert_eq!(m.adapter.name, "dev", "manifest read from /manifest.toml"); + assert_eq!( + m.adapter.name, "dev", + "manifest read from /manifest.toml" + ); // --manifest: install dir = the file's parent. - let (idir, m) = - resolve_proof_target(&adapters, "dev", None, Some(manifest_file.to_str().unwrap())) - .unwrap(); + let (idir, m) = resolve_proof_target( + &adapters, + "dev", + None, + Some(manifest_file.to_str().unwrap()), + ) + .unwrap(); assert_eq!(idir, devdir, "--manifest's parent is the install dir"); assert_eq!(m.adapter.name, "dev"); @@ -26050,8 +26619,14 @@ mod tests { // [unit->REQ-ADAPTER-VERSION-CMD] the subcommand parses to Version{option}. #[test] fn adapter_version_parses() { - match parse(&["spt", "adapter", "version", "claude-spt"]).unwrap().cmd.unwrap() { - Cmd::Adapter { action: AdapterCmd::Version { option } } => { + match parse(&["spt", "adapter", "version", "claude-spt"]) + .unwrap() + .cmd + .unwrap() + { + Cmd::Adapter { + action: AdapterCmd::Version { option }, + } => { assert_eq!(option, "claude-spt"); } _ => panic!("expected Adapter Version"), @@ -26069,10 +26644,16 @@ mod tests { let mut argv: Vec<&str> = crate::api::reporting::SHELL_HINT_VERB .split_whitespace() .collect(); - assert_eq!(argv.first().copied(), Some("spt"), "the verb names the binary"); + assert_eq!( + argv.first().copied(), + Some("spt"), + "the verb names the binary" + ); argv.push("some-adapter"); match parse(&argv).unwrap().cmd.unwrap() { - Cmd::Adapter { action: AdapterCmd::Hints { option } } => { + Cmd::Adapter { + action: AdapterCmd::Hints { option }, + } => { assert_eq!(option, "some-adapter"); } _ => panic!( @@ -26100,10 +26681,21 @@ mod tests { // The resolved manifest exposes exactly the declared [adapter].version — // the value `cmd_adapter_version` prints. let (_, m) = spt_runtime::registry::resolve_option(&adapters, "cc").unwrap(); - assert_eq!(m.adapter.version, "3.1.4", "the [adapter].version field is the source"); + assert_eq!( + m.adapter.version, "3.1.4", + "the [adapter].version field is the source" + ); - assert_eq!(cmd_adapter_version(&adapters, "cc", false), 0, "registered adapter → exit 0"); - assert_eq!(cmd_adapter_version(&adapters, "ghost", false), 1, "unregistered adapter → exit 1"); + assert_eq!( + cmd_adapter_version(&adapters, "cc", false), + 0, + "registered adapter → exit 0" + ); + assert_eq!( + cmd_adapter_version(&adapters, "ghost", false), + 1, + "unregistered adapter → exit 1" + ); } // [unit->REQ-ADAPTER-GH-TRANSPORT] The version command is the exact `gh api` @@ -26139,9 +26731,21 @@ mod tests { "gh release download {tag} --repo {repo} --pattern {asset} --dir {dir} --clobber", "tagged download template is the exact `gh release download ` form", ); - assert_eq!(keys.get("tag").map(String::as_str), Some("v0.13.2"), "tag key"); - assert_eq!(keys.get("repo").map(String::as_str), Some("Owner/repo"), "repo key"); - assert_eq!(keys.get("asset").map(String::as_str), Some("adapter.spt"), "asset key"); + assert_eq!( + keys.get("tag").map(String::as_str), + Some("v0.13.2"), + "tag key" + ); + assert_eq!( + keys.get("repo").map(String::as_str), + Some("Owner/repo"), + "repo key" + ); + assert_eq!( + keys.get("asset").map(String::as_str), + Some("adapter.spt"), + "asset key" + ); assert_eq!( keys.get("dir").map(String::as_str), Some(out_dir.to_string_lossy().as_ref()), @@ -26161,14 +26765,24 @@ mod tests { "latest-release template omits the {{tag}} token: {template}", ); assert_eq!( - template, - "gh release download --repo {repo} --pattern {asset} --dir {dir} --clobber", + template, "gh release download --repo {repo} --pattern {asset} --dir {dir} --clobber", "latest-release template is the exact no-tag-arg form", ); - assert!(!keys.contains_key("tag"), "no-tag form carries no `tag` key"); + assert!( + !keys.contains_key("tag"), + "no-tag form carries no `tag` key" + ); // The remaining keys are still fully populated. - assert_eq!(keys.get("repo").map(String::as_str), Some("Owner/repo"), "repo key"); - assert_eq!(keys.get("asset").map(String::as_str), Some("adapter.spt"), "asset key"); + assert_eq!( + keys.get("repo").map(String::as_str), + Some("Owner/repo"), + "repo key" + ); + assert_eq!( + keys.get("asset").map(String::as_str), + Some("adapter.spt"), + "asset key" + ); assert_eq!( keys.get("dir").map(String::as_str), Some(out_dir.to_string_lossy().as_ref()), @@ -26188,19 +26802,30 @@ mod tests { .cmd .unwrap() { - Cmd::Adapter { action: AdapterCmd::Add { gh, https, .. } } => { + Cmd::Adapter { + action: AdapterCmd::Add { gh, https, .. }, + } => { assert!(gh, "--gh sets gh=true"); assert!(!https, "--gh leaves https=false"); } _ => panic!("expected Adapter Add"), } // --https alone. - match parse(&["spt", "adapter", "add", "--release", "Owner/repo", "--https"]) - .unwrap() - .cmd - .unwrap() + match parse(&[ + "spt", + "adapter", + "add", + "--release", + "Owner/repo", + "--https", + ]) + .unwrap() + .cmd + .unwrap() { - Cmd::Adapter { action: AdapterCmd::Add { gh, https, .. } } => { + Cmd::Adapter { + action: AdapterCmd::Add { gh, https, .. }, + } => { assert!(https, "--https sets https=true"); assert!(!gh, "--https leaves gh=false"); } @@ -26212,14 +26837,25 @@ mod tests { .cmd .unwrap() { - Cmd::Adapter { action: AdapterCmd::Add { gh, https, .. } } => { + Cmd::Adapter { + action: AdapterCmd::Add { gh, https, .. }, + } => { assert!(!gh && !https, "neither flag → both false (auto)"); } _ => panic!("expected Adapter Add"), } // --gh --https together is rejected by conflicts_with. assert!( - parse(&["spt", "adapter", "add", "--release", "Owner/repo", "--gh", "--https"]).is_err(), + parse(&[ + "spt", + "adapter", + "add", + "--release", + "Owner/repo", + "--gh", + "--https" + ]) + .is_err(), "--gh and --https are mutually exclusive (clap conflicts_with)", ); } @@ -26241,7 +26877,10 @@ mod tests { spt_store::info::write_info(&perch, &rec).unwrap(); spt_store::info::set_status(&perch, spt_store::liveness::STATUS_ONLINE).unwrap(); spt_store::info::set_rest_state(&perch, "dormant", Some(1_000)).unwrap(); - assert!(spt_store::liveness::is_perch_alive(&perch), "online before stop"); + assert!( + spt_store::liveness::is_perch_alive(&perch), + "online before stop" + ); assert_eq!(cmd_stop(id), 0); @@ -26257,14 +26896,20 @@ mod tests { "stop normalizes the rest intent terminally" ); assert_eq!(got.dormant_since_ms, None, "anchor cleared with the pair"); - assert!(!spt_store::liveness::is_perch_alive(&perch), "offline after stop"); + assert!( + !spt_store::liveness::is_perch_alive(&perch), + "offline after stop" + ); // Already-offline + raw-Active input: stop still lands the full triple // (the surviving `active` intent is the wake order that must die). spt_store::info::set_rest_state(&perch, "active", None).unwrap(); assert_eq!(cmd_stop(id), 0); let got = spt_store::info::read_info(&perch).unwrap(); - assert_eq!(got.status.as_deref(), Some(spt_store::liveness::STATUS_OFFLINE)); + assert_eq!( + got.status.as_deref(), + Some(spt_store::liveness::STATUS_OFFLINE) + ); assert_eq!( got.rest_state.as_deref(), Some("suspended"), @@ -26316,7 +26961,8 @@ mod tests { let id = "askfirst"; let perch = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&perch).unwrap(); - let mut rec = spt_store::info::InfoJson::new(id, "t", std::process::id(), "sid", "live_agent"); + let mut rec = + spt_store::info::InfoJson::new(id, "t", std::process::id(), "sid", "live_agent"); // Broker-hosted: the topology on which the stop leg is a real teardown. rec.controllable = Some(true); spt_store::info::write_info(&perch, &rec).unwrap(); @@ -26340,7 +26986,10 @@ mod tests { "declining must leave the endpoint RUNNING — the stop leg is behind the confirm" ); assert_eq!( - spt_store::info::read_info(&perch).unwrap().status.as_deref(), + spt_store::info::read_info(&perch) + .unwrap() + .status + .as_deref(), Some(spt_store::liveness::STATUS_ONLINE), "a declined --force purge tears NOTHING down" ); @@ -26356,7 +27005,10 @@ mod tests { purge_endpoint_core(id, true, || true).outcome, PurgeOutcome::Purged )); - assert!(!perch.exists(), "an accepted --force purge removes the perch"); + assert!( + !perch.exists(), + "an accepted --force purge removes the perch" + ); } // The three mode facts of the named subnet view, worded for their @@ -26520,15 +27172,19 @@ mod tests { // Unelevated: refused before the confirm can even be asked. let mut asked = false; - let report = purge_endpoint_core_with(ENGINE_ROOM_ID, false, Elevation::NotElevated, || { - asked = true; - true - }); + let report = + purge_endpoint_core_with(ENGINE_ROOM_ID, false, Elevation::NotElevated, || { + asked = true; + true + }); assert!(matches!( report.outcome, PurgeOutcome::RefusedUnelevatedEngineRoom )); - assert!(!asked, "an unelevated caller is told no before being asked anything"); + assert!( + !asked, + "an unelevated caller is told no before being asked anything" + ); assert!(perch.exists(), "nothing was touched"); assert!( spt_store::engineroom::EngineRoom::load_from(&er_path).is_some(), @@ -26536,14 +27192,16 @@ mod tests { ); // Elevated: the records go, the binding goes, the outcome is a RESET. - let report = - purge_endpoint_core_with(ENGINE_ROOM_ID, false, Elevation::Elevated, || true); + let report = purge_endpoint_core_with(ENGINE_ROOM_ID, false, Elevation::Elevated, || true); assert!( matches!(report.outcome, PurgeOutcome::EngineRoomReset), "an engine-room purge reports a reset, never a purge: {:?}", report.outcome ); - assert!(!perch.exists(), "the reset wipes the records like any purge"); + assert!( + !perch.exists(), + "the reset wipes the records like any purge" + ); assert!( spt_store::engineroom::EngineRoom::load_from(&er_path).is_none(), "the binding is dropped, so the ceremony is the only way back online" @@ -26615,7 +27273,9 @@ mod tests { v.save().unwrap(); } assert!( - spt_store::visibility::VisibilityStore::load().sync_subnets(id).is_some(), + spt_store::visibility::VisibilityStore::load() + .sync_subnets(id) + .is_some(), "visibility sync row exists pre-purge" ); @@ -26624,7 +27284,10 @@ mod tests { // EVERY record gone. assert!(!perch.exists(), "the perch tree is gone"); - assert!(!psyche_perch.exists(), "the nested {id}-psyche perch is gone (recursive remove)"); + assert!( + !psyche_perch.exists(), + "the nested {id}-psyche perch is gone (recursive remove)" + ); assert!( spt_store::registry::lookup_address(id, &owlery).is_none(), "the registry address row is gone" @@ -26651,7 +27314,9 @@ mod tests { "the access row is gone" ); assert!( - spt_store::visibility::VisibilityStore::load().sync_subnets(id).is_none(), + spt_store::visibility::VisibilityStore::load() + .sync_subnets(id) + .is_none(), "the visibility rows are gone" ); } @@ -26680,20 +27345,29 @@ mod tests { // A relay listener registered → normal TCP delivery, NOT inject. let addr: std::net::SocketAddr = "127.0.0.1:6553".parse().unwrap(); spt_store::registry::register_address(id, &addr, &owlery).unwrap(); - assert!(!spt_daemon::is_spt_hosted_no_relay(id, &owlery), "a relay address takes the TCP path"); + assert!( + !spt_daemon::is_spt_hosted_no_relay(id, &owlery), + "a relay address takes the TCP path" + ); spt_store::registry::unregister_address(id, &owlery).unwrap(); // Not controllable (harness-hosted live agent) → not an inject target. rec.controllable = None; spt_store::info::write_info(&perch_path, &rec).unwrap(); spt_store::info::set_status(&perch_path, spt_store::liveness::STATUS_ONLINE).unwrap(); - assert!(!spt_daemon::is_spt_hosted_no_relay(id, &owlery), "non-controllable is not an inject target"); + assert!( + !spt_daemon::is_spt_hosted_no_relay(id, &owlery), + "non-controllable is not an inject target" + ); // Offline → not an inject target regardless. rec.controllable = Some(true); spt_store::info::write_info(&perch_path, &rec).unwrap(); spt_store::info::set_status(&perch_path, spt_store::liveness::STATUS_OFFLINE).unwrap(); - assert!(!spt_daemon::is_spt_hosted_no_relay(id, &owlery), "offline is not an inject target"); + assert!( + !spt_daemon::is_spt_hosted_no_relay(id, &owlery), + "offline is not an inject target" + ); } // [unit->REQ-ENDPOINT-LIST-NODE-GROUPED] [unit->REQ-ENDPOINT-LIST-PALETTE] @@ -26731,13 +27405,22 @@ mod tests { let lines: Vec<&str> = out.lines().collect(); assert_eq!(lines.len(), 2); assert!(!out.contains('\t'), "no tab separators"); - assert!(!out.contains("\x1b["), "color=false ⇒ no SGR escape bytes: {out:?}"); + assert!( + !out.contains("\x1b["), + "color=false ⇒ no SGR escape bytes: {out:?}" + ); // #11/#15: both rows read ONLINE (the shared EpDisplay label), never a raw // wire word; the absent type renders `-`. assert!(lines[0].contains(" - "), "absent type renders as -: {out}"); assert!(lines[1].contains("live_agent"), "{out}"); - assert!(lines[0].contains("ONLINE") && lines[1].contains("ONLINE"), "{out}"); - assert!(!out.contains("Dormant") && !out.contains("Active"), "no raw {{:?}} status: {out}"); + assert!( + lines[0].contains("ONLINE") && lines[1].contains("ONLINE"), + "{out}" + ); + assert!( + !out.contains("Dormant") && !out.contains("Active"), + "no raw {{:?}} status: {out}" + ); // Alignment: the status label starts at the SAME column on every row despite // variable-width ids. let col = |line: &str, word: &str| line.find(word).unwrap(); @@ -26748,7 +27431,10 @@ mod tests { ); // color=true wraps the square glyph in an SGR sequence (the picker palette). let colored = format_instance_rows(&cells, false, true); - assert!(colored.contains("\x1b["), "colored output carries SGR: {colored:?}"); + assert!( + colored.contains("\x1b["), + "colored output carries SGR: {colored:?}" + ); // [unit->REQ-ENDPOINT-LIST-RENDER-POLISH] A6 (c): the status GLYPH rides beside // the endpoint name — each row begins (past the indent) with the square glyph, // not the status word at the row end. @@ -26758,10 +27444,16 @@ mod tests { "each row starts with the status glyph beside the name: {out}" ); // A6 (d): the status WORD carries the palette color (green ONLINE), not just the square. - assert!(colored.contains("\x1b[32mONLINE"), "status word colored: {colored:?}"); + assert!( + colored.contains("\x1b[32mONLINE"), + "status word colored: {colored:?}" + ); // --detail adds the resources column. let detailed = format_instance_rows(&cells, true, false); - assert!(detailed.contains("blurb"), "detail surfaces resources: {detailed}"); + assert!( + detailed.contains("blurb"), + "detail surfaces resources: {detailed}" + ); } // [unit->REQ-ENDPOINT-LIST-PROJECT-COL] #8: the second column renders each @@ -26781,19 +27473,52 @@ mod tests { }; let cells = vec![ // Two DISTINCT dirs that derive the same `spt-core` slug → disambiguated. - cell("a", Some(ProjectRef { id: "spt-core".into(), dir: "C:/x/projects/spt-core".into(), display: "spt-core".into() })), - cell("b", Some(ProjectRef { id: "spt-core".into(), dir: "D:/spt-core".into(), display: "spt-core".into() })), + cell( + "a", + Some(ProjectRef { + id: "spt-core".into(), + dir: "C:/x/projects/spt-core".into(), + display: "spt-core".into(), + }), + ), + cell( + "b", + Some(ProjectRef { + id: "spt-core".into(), + dir: "D:/spt-core".into(), + display: "spt-core".into(), + }), + ), // A unique project → bare `owl/`. - cell("c", Some(ProjectRef { id: "owl".into(), dir: "C:/x/owl".into(), display: "owl".into() })), + cell( + "c", + Some(ProjectRef { + id: "owl".into(), + dir: "C:/x/owl".into(), + display: "owl".into(), + }), + ), // No project known → `-`. cell("d", None), ]; let out = format_instance_rows(&cells, false, false); let lines: Vec<&str> = out.lines().collect(); - assert!(lines[0].contains("spt-core (projects)/"), "collision disambiguated by parent: {out}"); - assert!(lines[1].contains("spt-core (D:)/"), "collision disambiguated by drive: {out}"); - assert!(lines[2].contains(" owl/ "), "unique project renders bare id + slash: {out}"); - assert!(lines[3].contains(" - "), "unknown project renders '-': {out}"); + assert!( + lines[0].contains("spt-core (projects)/"), + "collision disambiguated by parent: {out}" + ); + assert!( + lines[1].contains("spt-core (D:)/"), + "collision disambiguated by drive: {out}" + ); + assert!( + lines[2].contains(" owl/ "), + "unique project renders bare id + slash: {out}" + ); + assert!( + lines[3].contains(" - "), + "unknown project renders '-': {out}" + ); // The project column sits between id and status (id / / / type / status). assert!( lines[2].find(" owl/").unwrap() < lines[2].find("ONLINE").unwrap(), @@ -26815,7 +27540,11 @@ mod tests { Some("spt-core"), "remote head = newest gossiped project" ); - assert_eq!(cell.project_ref.as_ref().map(|r| r.dir.as_str()), Some(""), "no dir on the wire"); + assert_eq!( + cell.project_ref.as_ref().map(|r| r.dir.as_str()), + Some(""), + "no dir on the wire" + ); row.recent_projects.clear(); assert!( instance_cell_from_resource(&row).project_ref.is_none(), @@ -26837,8 +27566,15 @@ mod tests { endpoint_type: None, project: project.map(str::to_string), }; - assert!(serde_json::to_string(&remote(Some("spt-core"))).unwrap().contains("\"project\":\"spt-core\"")); - assert!(!serde_json::to_string(&remote(None)).unwrap().contains("project"), "None omits the key"); + assert!(serde_json::to_string(&remote(Some("spt-core"))) + .unwrap() + .contains("\"project\":\"spt-core\"")); + assert!( + !serde_json::to_string(&remote(None)) + .unwrap() + .contains("project"), + "None omits the key" + ); let local = |project: Option<&str>| LocalPerchJson { id: "e".into(), @@ -26852,8 +27588,15 @@ mod tests { host_error: None, drop_dir: None, }; - assert!(serde_json::to_string(&local(Some("owl"))).unwrap().contains("\"project\":\"owl\"")); - assert!(!serde_json::to_string(&local(None)).unwrap().contains("project"), "None omits the key"); + assert!(serde_json::to_string(&local(Some("owl"))) + .unwrap() + .contains("\"project\":\"owl\"")); + assert!( + !serde_json::to_string(&local(None)) + .unwrap() + .contains("project"), + "None omits the key" + ); } /// A LocalPerchJson with everything but `activity` fixed — the roster-survey @@ -26974,19 +27717,19 @@ mod tests { "live_agent", None, None, - self_pin_annotations( - None, - None, - None, - Some("C:/repo/.claude"), - ), + self_pin_annotations(None, None, None, Some("C:/repo/.claude")), ); assert!( with.contains("commune drop dir: C:/repo/.claude"), "a known drop dir is named on the pin: {with}" ); - let without = - render_self_pin("todlando", "live_agent", None, None, self_pin_annotations(None, None, None, None)); + let without = render_self_pin( + "todlando", + "live_agent", + None, + None, + self_pin_annotations(None, None, None, None), + ); assert!( !without.contains("commune drop dir"), "an unknown drop dir adds no line — omission is honest, a guess is not: {without}" @@ -26996,12 +27739,7 @@ mod tests { "live_agent", None, None, - self_pin_annotations( - None, - None, - None, - Some(" "), - ), + self_pin_annotations(None, None, None, Some(" ")), ); assert!( !blank.contains("commune drop dir"), @@ -27032,13 +27770,23 @@ mod tests { } // Build a gossiped ResourceRow for the node-grouped tests below. - fn res_row(id: &str, node: &str, label: &str, status: spt_net::net::registry::Status, epoch: u64) -> spt_net::net::registry::ResourceRow { + fn res_row( + id: &str, + node: &str, + label: &str, + status: spt_net::net::registry::Status, + epoch: u64, + ) -> spt_net::net::registry::ResourceRow { spt_net::net::registry::ResourceRow { endpoint_id: id.into(), node: node.into(), status, resources: None, - node_label: if label.is_empty() { None } else { Some(label.into()) }, + node_label: if label.is_empty() { + None + } else { + Some(label.into()) + }, bound: true, controller_node: None, harness_only: false, @@ -27059,8 +27807,14 @@ mod tests { fn node_group_same_id_two_nodes_two_groups() { use spt_net::net::registry::Status; let tagged = vec![ - ("home".to_string(), res_row("dup", "aaaa1111", "ALPHA", Status::Active, 1)), - ("home".to_string(), res_row("dup", "bbbb2222", "BRAVO", Status::Active, 1)), + ( + "home".to_string(), + res_row("dup", "aaaa1111", "ALPHA", Status::Active, 1), + ), + ( + "home".to_string(), + res_row("dup", "bbbb2222", "BRAVO", Status::Active, 1), + ), ]; let groups = group_remote_nodes("selfnode", tagged); assert_eq!(groups.len(), 2, "two nodes → two groups: {groups:?}"); @@ -27076,9 +27830,14 @@ mod tests { spt_net::net::registry::node_label_display("aaaa1111", Some("ALPHA")), "canonical LABEL (keyprefix…): {groups:?}" ); - assert!(groups[0].node_display.starts_with("ALPHA (") && groups[0].node_display.contains('…')); + assert!( + groups[0].node_display.starts_with("ALPHA (") && groups[0].node_display.contains('…') + ); assert!(groups[1].node_display.contains("BRAVO"), "{groups:?}"); - assert_ne!(groups[0].node_display, "aaaa1111", "must not leak bare key-hex"); + assert_ne!( + groups[0].node_display, "aaaa1111", + "must not leak bare key-hex" + ); } // [unit->REQ-ENDPOINT-LIST-NODE-GROUPED] the freshest-epoch twin rule: the SAME @@ -27091,17 +27850,30 @@ mod tests { use spt_net::net::registry::Status; // bignet: stale (epoch 1) Suspended; sptdev: fresh (epoch 5) Active. let tagged = vec![ - ("bignet".to_string(), res_row("eel", "node00hex", "REMOTE", Status::Suspended, 1)), - ("sptdev".to_string(), res_row("eel", "node00hex", "REMOTE", Status::Active, 5)), + ( + "bignet".to_string(), + res_row("eel", "node00hex", "REMOTE", Status::Suspended, 1), + ), + ( + "sptdev".to_string(), + res_row("eel", "node00hex", "REMOTE", Status::Active, 5), + ), ]; let groups = group_remote_nodes("selfnode", tagged); assert_eq!(groups.len(), 1, "one node group"); let g = &groups[0]; assert_eq!(g.cells.len(), 1, "subnet duplication collapsed to one row"); // The fresher (epoch 5, Active→Online) status wins over the stale Suspended. - assert_eq!(g.cells[0].display, EpDisplay::Online, "freshest epoch status wins"); + assert_eq!( + g.cells[0].display, + EpDisplay::Online, + "freshest epoch status wins" + ); // Both subnets unioned, sorted. - assert_eq!(g.shared_subnets, vec!["bignet".to_string(), "sptdev".to_string()]); + assert_eq!( + g.shared_subnets, + vec!["bignet".to_string(), "sptdev".to_string()] + ); } // [unit->REQ-ENDPOINT-LIST-NODE-GROUPED] this node's OWN gossip rows are @@ -27112,14 +27884,23 @@ mod tests { use spt_net::net::registry::Status; let tagged = vec![ // A row authored by THIS node — must be dropped. - ("home".to_string(), res_row("mine", "selfnode", "ME", Status::Active, 1)), + ( + "home".to_string(), + res_row("mine", "selfnode", "ME", Status::Active, 1), + ), // A genuine remote row — kept. - ("home".to_string(), res_row("theirs", "remotehex", "THEM", Status::Active, 1)), + ( + "home".to_string(), + res_row("theirs", "remotehex", "THEM", Status::Active, 1), + ), ]; let groups = group_remote_nodes("selfnode", tagged); assert_eq!(groups.len(), 1, "only the remote node forms a group"); assert!(groups[0].node_display.contains("THEM")); - assert!(groups[0].cells.iter().all(|c| c.id == "theirs"), "self row discarded"); + assert!( + groups[0].cells.iter().all(|c| c.id == "theirs"), + "self row discarded" + ); } // [unit->REQ-ENDPOINT-LIST-NODE-GROUPED] the whole node-grouped render: This @@ -27147,23 +27928,36 @@ mod tests { let this = vec![cell("doyle", "live_agent")]; let nested = vec![cell("doyle-psyche", "psyche"), cell("zeta", "worker")]; - let out = - render_node_grouped( - &ThisNodeGroup { ident: "HOST (a1…)", joined_subnets: &[], cells: &this, own_nested: &nested, own_companions: &[] }, + let out = render_node_grouped( + &ThisNodeGroup { + ident: "HOST (a1…)", + joined_subnets: &[], + cells: &this, + own_nested: &nested, + own_companions: &[], + }, &[], false, false, false, ); let total_at = out.find(" Total: 1\n").expect("this-node Total"); - let label_at = out.find(" Your nested perches:").expect("the section renders"); - assert!(total_at < label_at, "the section sits AFTER the Total: {out}"); + let label_at = out + .find(" Your nested perches:") + .expect("the section renders"); + assert!( + total_at < label_at, + "the section sits AFTER the Total: {out}" + ); assert!( out.find("doyle-psyche").expect("the psyche row") > label_at, "the children sit under their heading: {out}" ); // Named whatever it likes — the section is structural, never name-matched. - assert!(out.contains("zeta"), "an oddly-named nested perch still renders: {out}"); + assert!( + out.contains("zeta"), + "an oddly-named nested perch still renders: {out}" + ); // The disclosed count is untouched by the children. assert_eq!(out.matches("Total:").count(), 1, "one Total: {out}"); assert!( @@ -27173,13 +27967,22 @@ mod tests { // No children — or no caller the seam could resolve — means no heading. let bare = render_node_grouped( - &ThisNodeGroup { ident: "HOST (a1…)", joined_subnets: &[], cells: &this, own_nested: &[], own_companions: &[] }, + &ThisNodeGroup { + ident: "HOST (a1…)", + joined_subnets: &[], + cells: &this, + own_nested: &[], + own_companions: &[], + }, &[], false, false, false, ); - assert!(!bare.contains("Your nested perches"), "no empty heading: {bare}"); + assert!( + !bare.contains("Your nested perches"), + "no empty heading: {bare}" + ); assert!(bare.contains(" Total: 1\n"), "{bare}"); } @@ -27230,7 +28033,10 @@ mod tests { } assert!(line.contains("status not recorded"), "{line:?}"); // The bound sibling KEEPS its square — the two kinds stay distinguishable. - let bound_line = out.lines().find(|l| l.contains("me-w1")).expect("the bound row"); + let bound_line = out + .lines() + .find(|l| l.contains("me-w1")) + .expect("the bound row"); assert!( bound_line.contains("ONLINE"), "a bound row keeps its status: {bound_line:?}" @@ -27285,13 +28091,23 @@ mod tests { // The two subnet sets DIFFER on purpose (#72): homenet is joined here and // gossiped by nobody, so the This-node line and the remote line can no // longer stand in for one another in an assertion. - let our = vec!["bignet".to_string(), "sptdev".to_string(), "homenet".to_string()]; + let our = vec![ + "bignet".to_string(), + "sptdev".to_string(), + "homenet".to_string(), + ]; let out = format_instance_rows(&this, false, false); // sanity assert!(!out.is_empty()); // Color OFF: no SGR bytes anywhere. let plain = render_node_grouped( - &ThisNodeGroup { ident: "HOST (a1b2…)", joined_subnets: &our, cells: &this, own_nested: &[], own_companions: &[] }, + &ThisNodeGroup { + ident: "HOST (a1b2…)", + joined_subnets: &our, + cells: &this, + own_nested: &[], + own_companions: &[], + }, &remote, false, false, @@ -27299,9 +28115,14 @@ mod tests { ); assert!(!plain.contains("\x1b["), "color off ⇒ no SGR: {plain:?}"); // This node FIRST, then the remote node. - let this_at = plain.find("This node: HOST (a1b2…)").expect("This-node header"); + let this_at = plain + .find("This node: HOST (a1b2…)") + .expect("This-node header"); let rem_at = plain.find("REMOTE (dead…)").expect("remote header"); - assert!(this_at < rem_at, "This node renders before the remote node: {plain}"); + assert!( + this_at < rem_at, + "This node renders before the remote node: {plain}" + ); // Our JOINED subnets under This node; the remote's SHARED (intersected) // subnets under its own header — two labels, two facts, asserted apart. // [unit->REQ-ENDPOINT-LIST-JOINED-SUBNETS-LABEL] @@ -27324,21 +28145,43 @@ mod tests { "exactly one Shared line — the This-node row must not still be Shared: {plain}" ); // Per-node Total lines; NO grand total, NO ENDPOINTS line. - assert_eq!(plain.matches("Total:").count(), 2, "one Total per node: {plain}"); + assert_eq!( + plain.matches("Total:").count(), + 2, + "one Total per node: {plain}" + ); assert!(plain.contains(" Total: 1\n"), "{plain}"); - assert!(!plain.contains("ENDPOINTS:"), "the stderr ENDPOINTS line is removed: {plain}"); - assert!(!plain.to_lowercase().contains("grand total"), "no grand total: {plain}"); + assert!( + !plain.contains("ENDPOINTS:"), + "the stderr ENDPOINTS line is removed: {plain}" + ); + assert!( + !plain.to_lowercase().contains("grand total"), + "no grand total: {plain}" + ); // Color ON: cyan This-node header + orange remote header. let colored = render_node_grouped( - &ThisNodeGroup { ident: "HOST (a1b2…)", joined_subnets: &our, cells: &this, own_nested: &[], own_companions: &[] }, + &ThisNodeGroup { + ident: "HOST (a1b2…)", + joined_subnets: &our, + cells: &this, + own_nested: &[], + own_companions: &[], + }, &remote, false, false, true, ); - assert!(colored.contains("\x1b[36mThis node: HOST (a1b2…)\x1b[0m"), "cyan This node: {colored:?}"); - assert!(colored.contains("\x1b[38;5;208mREMOTE (dead…)\x1b[0m"), "orange remote: {colored:?}"); + assert!( + colored.contains("\x1b[36mThis node: HOST (a1b2…)\x1b[0m"), + "cyan This node: {colored:?}" + ); + assert!( + colored.contains("\x1b[38;5;208mREMOTE (dead…)\x1b[0m"), + "orange remote: {colored:?}" + ); } // [unit->REQ-ENDPOINT-LIST-MERGE-LOCAL] [unit->REQ-ENDPOINT-LIST-NODE-IDENT] @@ -27382,27 +28225,54 @@ mod tests { // Rendered: header names THIS node; the unbound row shows the UNBOUND label. let out = render_node_grouped( - &ThisNodeGroup { ident: "hfenduleam (a1b2…)", joined_subnets: &[], cells: &[alive_cell, unbound_cell], own_nested: &[], own_companions: &[] }, + &ThisNodeGroup { + ident: "hfenduleam (a1b2…)", + joined_subnets: &[], + cells: &[alive_cell, unbound_cell], + own_nested: &[], + own_companions: &[], + }, &[], false, false, false, ); - assert!(out.contains("This node: hfenduleam (a1b2…)"), "header names this node: {out}"); - assert!(out.contains("freshself") && out.contains("skeleton"), "both perches listed: {out}"); - assert!(out.contains("UNBOUND"), "the unbound seat carries the UNBOUND label: {out}"); - assert!(out.contains(" Total: 2\n"), "this-node Total counts the roster: {out}"); + assert!( + out.contains("This node: hfenduleam (a1b2…)"), + "header names this node: {out}" + ); + assert!( + out.contains("freshself") && out.contains("skeleton"), + "both perches listed: {out}" + ); + assert!( + out.contains("UNBOUND"), + "the unbound seat carries the UNBOUND label: {out}" + ); + assert!( + out.contains(" Total: 2\n"), + "this-node Total counts the roster: {out}" + ); // Empty roster ⇒ header + quiet marker, Total 0. let empty = render_node_grouped( - &ThisNodeGroup { ident: "somenode (dead…)", joined_subnets: &[], cells: &[], own_nested: &[], own_companions: &[] }, + &ThisNodeGroup { + ident: "somenode (dead…)", + joined_subnets: &[], + cells: &[], + own_nested: &[], + own_companions: &[], + }, &[], false, false, false, ); assert!(empty.contains("This node: somenode (dead…)")); - assert!(empty.contains("(no local perches)"), "empty roster ⇒ quiet marker: {empty}"); + assert!( + empty.contains("(no local perches)"), + "empty roster ⇒ quiet marker: {empty}" + ); assert!(empty.contains(" Total: 0\n"), "{empty}"); } @@ -27438,7 +28308,10 @@ mod tests { ids.contains(&"online") && ids.contains(&"broken"), "corrupt ALWAYS shows: {ids:?}" ); - assert!(!ids.contains(&"resting"), "plain suspended hidden by default: {ids:?}"); + assert!( + !ids.contains(&"resting"), + "plain suspended hidden by default: {ids:?}" + ); let (all, hidden_all) = filter_and_order(&cells, true); assert_eq!(hidden_all, 0, "show_all hides nothing"); assert_eq!(all.len(), 3, "show_all reveals the resting row too"); @@ -27479,11 +28352,17 @@ mod tests { fn rest_filter_total_disclosure_and_corrupt_annotation() { use crate::picker::model::EpDisplay; // color=false → plain body (no SGR); A6 (b) adds the dim wrap only under color. - assert_eq!(render_total(2, 3, false), " Total: 2 (+3 suspended hidden)\n"); + assert_eq!( + render_total(2, 3, false), + " Total: 2 (+3 suspended hidden)\n" + ); assert_eq!(render_total(2, 0, false), " Total: 2\n"); // [unit->REQ-ENDPOINT-LIST-RENDER-POLISH] A6 (b): under color the Total takes // the dim-gray SGR 90 chrome, same as the Shared-subnets line. - assert!(render_total(2, 0, true).contains("\x1b[90m"), "Total dim under color"); + assert!( + render_total(2, 0, true).contains("\x1b[90m"), + "Total dim under color" + ); let corrupt = vec![icell("broken", EpDisplay::Offline, true)]; let out = format_instance_rows(&corrupt, false, false); assert!(out.contains("CORRUPT"), "corrupt row annotated: {out}"); @@ -27508,7 +28387,10 @@ mod tests { project: None, }; let s = serde_json::to_string(&with).unwrap(); - assert!(s.contains("\"endpoint_type\":\"live_agent\""), "advertised type present: {s}"); + assert!( + s.contains("\"endpoint_type\":\"live_agent\""), + "advertised type present: {s}" + ); let without = EndpointRowJson { id: "x".into(), node: "n".into(), @@ -27767,7 +28649,10 @@ mod tests { "only the row that genuinely lacks a node says so: {out}" ); assert!( - out.contains(&spt_net::net::registry::node_label_display("aa11bb22cc33dd44", None)), + out.contains(&spt_net::net::registry::node_label_display( + "aa11bb22cc33dd44", + None + )), "the row that has a node renders it the way every other surface does: {out}" ); } @@ -27861,7 +28746,13 @@ mod tests { use crate::picker::model::EpDisplay; let this = vec![icell("resting", EpDisplay::Suspended, false)]; let out = render_node_grouped( - &ThisNodeGroup { ident: "HOST (a1…)", joined_subnets: &[], cells: &this, own_nested: &[], own_companions: &[] }, + &ThisNodeGroup { + ident: "HOST (a1…)", + joined_subnets: &[], + cells: &this, + own_nested: &[], + own_companions: &[], + }, &[], false, false, @@ -27876,7 +28767,13 @@ mod tests { "the disclosure speaks for the hidden rows: {out}" ); let empty = render_node_grouped( - &ThisNodeGroup { ident: "HOST (a1…)", joined_subnets: &[], cells: &[], own_nested: &[], own_companions: &[] }, + &ThisNodeGroup { + ident: "HOST (a1…)", + joined_subnets: &[], + cells: &[], + own_nested: &[], + own_companions: &[], + }, &[], false, false, @@ -27888,7 +28785,6 @@ mod tests { ); } - // [unit->REQ-UPD-9] the gh_release version-compare decision: a strictly-newer // latest release ripples (update), a same/older one does not (skip). Dotted // numeric ordering with missing components as 0; an unparseable tag is treated @@ -27936,7 +28832,10 @@ mod tests { // Pack the archive with the same `tar` the extractor unpacks with. let archive = tmp.path().join("adapter.spt"); let keys = std::collections::BTreeMap::from([ - ("archive".to_string(), archive.to_string_lossy().into_owned()), + ( + "archive".to_string(), + archive.to_string_lossy().into_owned(), + ), ("src".to_string(), src.to_string_lossy().into_owned()), ]); spt_runtime::run_bounded_command( @@ -27978,7 +28877,10 @@ mod tests { .unwrap(); let archive = tmp.join(format!("{name}.spt")); let keys = std::collections::BTreeMap::from([ - ("archive".to_string(), archive.to_string_lossy().into_owned()), + ( + "archive".to_string(), + archive.to_string_lossy().into_owned(), + ), ("src".to_string(), src.to_string_lossy().into_owned()), ]); spt_runtime::run_bounded_command( @@ -28006,7 +28908,10 @@ mod tests { assert!(!dest.exists(), "precondition: dest starts absent"); let res = staged_floor_ok(&archive, &dest, "hifloor", env!("CARGO_PKG_VERSION")); - assert!(res.is_err(), "a staged floor above the core must refuse the swap"); + assert!( + res.is_err(), + "a staged floor above the core must refuse the swap" + ); let msg = res.unwrap_err(); assert!( msg.contains("9.9.9") && msg.contains("hifloor"), @@ -28014,7 +28919,10 @@ mod tests { ); // The live home was never touched, and the throwaway peek dir is gone. - assert!(!dest.exists(), "a refused peek must NOT create the live dest home"); + assert!( + !dest.exists(), + "a refused peek must NOT create the live dest home" + ); assert!( !dest.with_extension("floor-peek").exists(), "the throwaway .floor-peek temp is removed on exit" @@ -28031,7 +28939,10 @@ mod tests { let dest = tmp.path().join("live-home"); let res = staged_floor_ok(&archive, &dest, "lofloor", env!("CARGO_PKG_VERSION")); - assert!(res.is_ok(), "a staged floor the core clears must peek OK: {res:?}"); + assert!( + res.is_ok(), + "a staged floor the core clears must peek OK: {res:?}" + ); assert!(!dest.exists(), "the peek never writes dest, even on Ok"); assert!( !dest.with_extension("floor-peek").exists(), @@ -28203,7 +29114,8 @@ mod tests { spt_runtime::registry::register_with_core(&adapters, &src, 1000, basis).is_ok(); assert_eq!( - peek, expect_admit, + peek, + expect_admit, "the pre-swap peek must {} a 5.0.0 floor judged at {basis}", if expect_admit { "admit" } else { "refuse" } ); @@ -28232,9 +29144,21 @@ mod tests { #[test] fn bare_tty_guard() { assert_eq!(decide_bare(true, true), BareAction::Picker); - assert_eq!(decide_bare(false, true), BareAction::Help, "piped stdin → help"); - assert_eq!(decide_bare(true, false), BareAction::Help, "redirected stdout → help"); - assert_eq!(decide_bare(false, false), BareAction::Help, "CI/non-tty → help"); + assert_eq!( + decide_bare(false, true), + BareAction::Help, + "piped stdin → help" + ); + assert_eq!( + decide_bare(true, false), + BareAction::Help, + "redirected stdout → help" + ); + assert_eq!( + decide_bare(false, false), + BareAction::Help, + "CI/non-tty → help" + ); } // [unit->REQ-MSG-5] the LOCAL origination gate: a bare CLI (no agent @@ -28264,7 +29188,8 @@ mod tests { &spt_store::info::InfoJson::new(agent, "t", std::process::id(), "s", "live_agent"), ) .unwrap(); - let (body, restamped) = apply_user_msg_gate(Some(agent), agent, "ship it", true, None, None); + let (body, restamped) = + apply_user_msg_gate(Some(agent), agent, "ship it", true, None, None); assert!(restamped, "agent sender re-stamped"); assert_eq!(body, "ship it", "plain body, no envelope"); @@ -28277,7 +29202,8 @@ mod tests { &spt_store::info::InfoJson::new(gw, "t", std::process::id(), "s", "gateway"), ) .unwrap(); - let (body, restamped) = apply_user_msg_gate(Some(gw), gw, "from the device", true, None, None); + let (body, restamped) = + apply_user_msg_gate(Some(gw), gw, "from the device", true, None, None); assert!(!restamped); assert_eq!( parse_event(&body).unwrap().event_type.as_deref(), @@ -28309,8 +29235,15 @@ mod tests { let p = parse_event(&body).expect("composed a typed envelope"); assert_eq!(p.event_type.as_deref(), Some("msg")); assert_eq!(p.from(), Some("me")); - assert_eq!(p.body, "hello", "json rides ALONGSIDE the body, never replacing it"); - assert_eq!(p.attr("json"), Some(r#"{"k":"v"}"#), "json attr round-trips"); + assert_eq!( + p.body, "hello", + "json rides ALONGSIDE the body, never replacing it" + ); + assert_eq!( + p.attr("json"), + Some(r#"{"k":"v"}"#), + "json attr round-trips" + ); // user-msg + json: honored type carries the json attr too. let (body, _) = apply_user_msg_gate(None, "me", "ship", true, Some(r#"{"n":1}"#), None); @@ -28319,10 +29252,20 @@ mod tests { assert_eq!(p.attr("json"), Some(r#"{"n":1}"#)); // A json value with a quote attr-escapes (no envelope corruption / forgery). - let (body, _) = - apply_user_msg_gate(None, "me", "x", false, Some(r#"{"q":"a\"b","from":"evil"}"#), None); + let (body, _) = apply_user_msg_gate( + None, + "me", + "x", + false, + Some(r#"{"q":"a\"b","from":"evil"}"#), + None, + ); let p = parse_event(&body).expect("attr-escaped json parses cleanly"); - assert_eq!(p.from(), Some("me"), "the real from is intact — json can't forge it"); + assert_eq!( + p.from(), + Some("me"), + "the real from is intact — json can't forge it" + ); assert_eq!(p.body, "x"); } @@ -28353,7 +29296,10 @@ mod tests { ); } assert_eq!(seal_answer("SENT:doyle".to_string(), None), "SENT:doyle"); - assert_eq!(seal_answer("QUEUED:doyle".to_string(), None), "QUEUED:doyle"); + assert_eq!( + seal_answer("QUEUED:doyle".to_string(), None), + "QUEUED:doyle" + ); } // [unit->REQ-SEAL-SEND-SEALED] the --seal axis parses (--subnet requires @@ -28409,7 +29355,10 @@ mod tests { ); let p = parse_event(&body).unwrap(); assert_eq!(p.attr("json"), Some(r#"{"n":1}"#)); - assert_eq!(p.attr(spt_proto::event::EVENT_ATTR_SEAL), Some("bcdfgh2345")); + assert_eq!( + p.attr(spt_proto::event::EVENT_ATTR_SEAL), + Some("bcdfgh2345") + ); } // [unit->REQ-EP-7] `spt endpoint role` is the SOLE writer: --overwrite @@ -28544,11 +29493,7 @@ mod tests { .max() .unwrap(); for sc in cmd.get_subcommands().filter(|s| !s.is_hide_set()) { - assert!( - sc.get_about().is_some(), - "{} needs an about", - sc.get_name() - ); + assert!(sc.get_about().is_some(), "{} needs an about", sc.get_name()); // The MEASURED row is the RENDERED row, alias suffix included // (releases#112) — measuring the bare about would leave a command's // visible aliases outside the width contract they widen. @@ -28586,17 +29531,32 @@ mod tests { fn ring_timeout_parses_bare_as_minutes_and_honors_suffixes() { use std::time::Duration as D; // Bare = MINUTES: 30 is half an hour, not half a minute. - assert_eq!(parse_ring_timeout("30").unwrap().duration(), D::from_secs(30 * 60)); - assert_eq!(parse_ring_timeout("2").unwrap().duration(), D::from_secs(120)); + assert_eq!( + parse_ring_timeout("30").unwrap().duration(), + D::from_secs(30 * 60) + ); + assert_eq!( + parse_ring_timeout("2").unwrap().duration(), + D::from_secs(120) + ); // An explicit `s` keeps sub-minute waits expressible. - assert_eq!(parse_ring_timeout("90s").unwrap().duration(), D::from_secs(90)); - assert_eq!(parse_ring_timeout("1s").unwrap().duration(), D::from_secs(1)); + assert_eq!( + parse_ring_timeout("90s").unwrap().duration(), + D::from_secs(90) + ); + assert_eq!( + parse_ring_timeout("1s").unwrap().duration(), + D::from_secs(1) + ); // An explicit `m` AGREES with the bare form rather than forming a third rule. assert_eq!( parse_ring_timeout("2m").unwrap().duration(), parse_ring_timeout("2").unwrap().duration() ); - assert_eq!(parse_ring_timeout(" 45s ").unwrap().duration(), D::from_secs(45)); + assert_eq!( + parse_ring_timeout(" 45s ").unwrap().duration(), + D::from_secs(45) + ); // Garbage is REFUSED, never defaulted into a wait nobody chose. for bad in ["", "s", "m", "abc", "5x", "-5", "5 s", "1.5m", "m5", "1h"] { assert!(parse_ring_timeout(bad).is_err(), "{bad:?} must be refused"); @@ -28639,44 +29599,84 @@ mod tests { assert!(matches!( parse(&["spt", "send", "bob", "--from", "alice"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Send { .. } )); assert!(matches!( - parse(&["spt", "send", "bob", "--active-only"]).unwrap().cmd.unwrap(), - Cmd::Send { active_only: true, .. } + parse(&["spt", "send", "bob", "--active-only"]) + .unwrap() + .cmd + .unwrap(), + Cmd::Send { + active_only: true, + .. + } )); assert!(matches!( - parse(&["spt", "send", "bob", "--idle-only", "--ephemeral"]).unwrap().cmd.unwrap(), - Cmd::Send { idle_only: true, ephemeral: true, .. } + parse(&["spt", "send", "bob", "--idle-only", "--ephemeral"]) + .unwrap() + .cmd + .unwrap(), + Cmd::Send { + idle_only: true, + ephemeral: true, + .. + } )); // --idle-only and --active-only are mutually exclusive. assert!(parse(&["spt", "send", "bob", "--idle-only", "--active-only"]).is_err()); // Hidden back-compat alias: the old `--deferred` still parses → active_only. assert!(matches!( - parse(&["spt", "send", "bob", "--deferred"]).unwrap().cmd.unwrap(), - Cmd::Send { active_only: true, .. } + parse(&["spt", "send", "bob", "--deferred"]) + .unwrap() + .cmd + .unwrap(), + Cmd::Send { + active_only: true, + .. + } )); // W3 channel axis: --prefer-native / --force-native, mutually exclusive, // composing with the window axis (--force-native --active-only is valid). assert!(matches!( - parse(&["spt", "send", "bob", "--prefer-native"]).unwrap().cmd.unwrap(), - Cmd::Send { prefer_native: true, .. } + parse(&["spt", "send", "bob", "--prefer-native"]) + .unwrap() + .cmd + .unwrap(), + Cmd::Send { + prefer_native: true, + .. + } )); assert!(matches!( - parse(&["spt", "send", "bob", "--force-native", "--active-only"]).unwrap().cmd.unwrap(), - Cmd::Send { force_native: true, active_only: true, .. } + parse(&["spt", "send", "bob", "--force-native", "--active-only"]) + .unwrap() + .cmd + .unwrap(), + Cmd::Send { + force_native: true, + active_only: true, + .. + } )); assert!(parse(&["spt", "send", "bob", "--prefer-native", "--force-native"]).is_err()); // W4 metadata axis: --json-payload carries an opaque blob. assert!(matches!( - parse(&["spt", "send", "bob", "--json-payload", "{\"k\":1}"]).unwrap().cmd.unwrap(), - Cmd::Send { json_payload: Some(_), .. } + parse(&["spt", "send", "bob", "--json-payload", "{\"k\":1}"]) + .unwrap() + .cmd + .unwrap(), + Cmd::Send { + json_payload: Some(_), + .. + } )); assert!(matches!( parse(&["spt", "ring", "bob", "--timeout", "5"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Ring { .. } )); assert!(matches!( @@ -28686,7 +29686,10 @@ mod tests { // [unit->REQ-MSG-2] `ready --once` absorbs the removed `poll`'s // drain-then-exit semantics (M7 plan decision 2); `poll` itself is gone. assert!(matches!( - parse(&["spt", "ready", "bob", "--once"]).unwrap().cmd.unwrap(), + parse(&["spt", "ready", "bob", "--once"]) + .unwrap() + .cmd + .unwrap(), Cmd::Ready { once: true, .. } )); assert!( @@ -28704,51 +29707,67 @@ mod tests { // and omits it (no trailing separator) when the blurb is absent or blank. #[test] fn self_pin_includes_description_when_present() { - let with = - render_self_pin( + let with = render_self_pin( "ling", "Ready ready=true alive=true", Some("triage bot"), None, - self_pin_annotations( - None, - None, - None, - None, - ), + self_pin_annotations(None, None, None, None), + ); + assert!( + with.starts_with("SELF: ling "), + "id-first SELF pin: {with}" ); - assert!(with.starts_with("SELF: ling "), "id-first SELF pin: {with}"); assert!(with.contains("triage bot"), "description rendered: {with}"); // Absent / blank blurb → no description, no dangling separator. - let without = render_self_pin("ling", "Ready", None, None, self_pin_annotations(None, None, None, None)); + let without = render_self_pin( + "ling", + "Ready", + None, + None, + self_pin_annotations(None, None, None, None), + ); assert_eq!(without, "SELF: ling Ready"); - let blank = render_self_pin("ling", "Ready", Some(" "), None, self_pin_annotations(None, None, None, None)); - assert_eq!(blank, "SELF: ling Ready", "whitespace blurb treated as absent"); + let blank = render_self_pin( + "ling", + "Ready", + Some(" "), + None, + self_pin_annotations(None, None, None, None), + ); + assert_eq!( + blank, "SELF: ling Ready", + "whitespace blurb treated as absent" + ); // [unit->REQ-ENDPOINT-LIST-NODE-GROUPED] the SELF pin names THIS node with a // `(self @ )` marker (the node-grouped view pins SELF first, naming its // home node inline); a blank/absent node adds no marker. - let pinned = - render_self_pin( + let pinned = render_self_pin( "ling", "Ready", Some("triage bot"), Some("HFENDULEAM (a1b2…)"), - self_pin_annotations( - None, - None, - None, - None, - ), + self_pin_annotations(None, None, None, None), ); assert!( pinned.contains("(self @ HFENDULEAM (a1b2…))"), "the pin names this node: {pinned}" ); // The marker rides the SELF identity line (not a separate line). - assert_eq!(pinned.lines().count(), 1, "marker stays on the SELF line: {pinned}"); - let unmarked = render_self_pin("ling", "Ready", None, Some(" "), self_pin_annotations(None, None, None, None)); + assert_eq!( + pinned.lines().count(), + 1, + "marker stays on the SELF line: {pinned}" + ); + let unmarked = render_self_pin( + "ling", + "Ready", + None, + Some(" "), + self_pin_annotations(None, None, None, None), + ); assert_eq!(unmarked, "SELF: ling Ready", "a blank node adds no marker"); } @@ -28769,17 +29788,24 @@ mod tests { "live_agent ready=true alive=true online", None, None, - self_pin_annotations( - Some(&err), - None, - None, - None, - ), + self_pin_annotations(Some(&err), None, None, None), + ); + assert!( + out.contains("online"), + "status still rendered authoritatively: {out}" + ); + assert!( + out.contains("psyche-host: FAILED"), + "failure annotated: {out}" + ); + assert!( + out.contains("psychebin: program not found"), + "reason inline: {out}" + ); + assert!( + out.contains("3 attempts"), + "attempts inline (pluralized): {out}" ); - assert!(out.contains("online"), "status still rendered authoritatively: {out}"); - assert!(out.contains("psyche-host: FAILED"), "failure annotated: {out}"); - assert!(out.contains("psychebin: program not found"), "reason inline: {out}"); - assert!(out.contains("3 attempts"), "attempts inline (pluralized): {out}"); assert!(out.contains("2026-06-16T00:00:00Z"), "ts inline: {out}"); // attempts == 1 → singular "attempt". @@ -28791,12 +29817,27 @@ mod tests { // renderers below read reason/attempts/ts and nothing else. slots: std::collections::BTreeMap::new(), }; - let out1 = render_self_pin("ling", "live_agent", None, None, self_pin_annotations(Some(&one), None, None, None)); + let out1 = render_self_pin( + "ling", + "live_agent", + None, + None, + self_pin_annotations(Some(&one), None, None, None), + ); assert!(out1.contains("1 attempt;"), "singular attempt: {out1}"); // No error → no annotation line. - let clean = render_self_pin("ling", "live_agent", None, None, self_pin_annotations(None, None, None, None)); - assert!(!clean.contains("psyche-host"), "no annotation when clean: {clean}"); + let clean = render_self_pin( + "ling", + "live_agent", + None, + None, + self_pin_annotations(None, None, None, None), + ); + assert!( + !clean.contains("psyche-host"), + "no annotation when clean: {clean}" + ); } // [unit->REQ-PUBLIC-ERROR-SURFACES] F-1 (the F-030 seed): a broker-stamped @@ -28811,16 +29852,20 @@ mod tests { "live_agent ready=true alive=true online", None, None, - self_pin_annotations( - None, - Some("inject worker panicked"), - None, - None, - ), + self_pin_annotations(None, Some("inject worker panicked"), None, None), + ); + assert!( + out.contains("input-translation: FAILED"), + "fault annotated: {out}" + ); + assert!( + out.contains("inject worker panicked"), + "reason inline: {out}" + ); + assert!( + out.contains("spt endpoint start"), + "next action named: {out}" ); - assert!(out.contains("input-translation: FAILED"), "fault annotated: {out}"); - assert!(out.contains("inject worker panicked"), "reason inline: {out}"); - assert!(out.contains("spt endpoint start"), "next action named: {out}"); // Composes with the psyche-host annotation (both lines, order stable). let err = spt_store::info::PsycheHostError { @@ -28836,12 +29881,7 @@ mod tests { "live_agent", None, None, - self_pin_annotations( - Some(&err), - Some("why"), - None, - None, - ), + self_pin_annotations(Some(&err), Some("why"), None, None), ); assert!(both.contains("psyche-host: FAILED") && both.contains("input-translation: FAILED")); @@ -28851,14 +29891,12 @@ mod tests { "live_agent", None, None, - self_pin_annotations( - None, - Some(" "), - None, - None, - ), + self_pin_annotations(None, Some(" "), None, None), + ); + assert!( + !blank.contains("input-translation"), + "blank fault adds no line: {blank}" ); - assert!(!blank.contains("input-translation"), "blank fault adds no line: {blank}"); } // [unit->REQ-PUBLIC-ERROR-SURFACES] straggler (4), the A-2 host_error report: @@ -28879,17 +29917,32 @@ mod tests { None, None, Some( - "recorded session adapter 'ghost' is not a registered/active adapter \ + "recorded session adapter 'ghost' is not a registered/active adapter \ on this node — register it (spt adapter add)", - ), + ), None, ), ); - assert!(out.contains("host: FAILED"), "host failure annotated: {out}"); - assert!(out.contains("could not host or resume"), "situation named: {out}"); - assert!(out.contains("'ghost'"), "reason inline (names the adapter): {out}"); - assert!(out.contains("spt adapter add"), "the reason's own next action survives: {out}"); - assert!(out.contains("online"), "status still rendered authoritatively: {out}"); + assert!( + out.contains("host: FAILED"), + "host failure annotated: {out}" + ); + assert!( + out.contains("could not host or resume"), + "situation named: {out}" + ); + assert!( + out.contains("'ghost'"), + "reason inline (names the adapter): {out}" + ); + assert!( + out.contains("spt adapter add"), + "the reason's own next action survives: {out}" + ); + assert!( + out.contains("online"), + "status still rendered authoritatively: {out}" + ); // All three annotations compose, one render pass, order stable. let err = spt_store::info::PsycheHostError { @@ -28905,12 +29958,7 @@ mod tests { "live_agent", None, None, - self_pin_annotations( - Some(&err), - Some("why"), - Some("adapter gone"), - None, - ), + self_pin_annotations(Some(&err), Some("why"), Some("adapter gone"), None), ); let (phe_at, tf_at, he_at) = ( all.find("psyche-host: FAILED"), @@ -28924,21 +29972,28 @@ mod tests { assert!(phe_at < tf_at && tf_at < he_at, "order stable: {all}"); // Absent → no line; blank → treated as absent. - let clean = render_self_pin("ling", "live_agent", None, None, self_pin_annotations(None, None, None, None)); - assert!(!clean.contains("host: FAILED"), "no annotation when clean: {clean}"); + let clean = render_self_pin( + "ling", + "live_agent", + None, + None, + self_pin_annotations(None, None, None, None), + ); + assert!( + !clean.contains("host: FAILED"), + "no annotation when clean: {clean}" + ); let blank = render_self_pin( "ling", "live_agent", None, None, - self_pin_annotations( - None, - None, - Some(" "), - None, - ), + self_pin_annotations(None, None, Some(" "), None), + ); + assert!( + !blank.contains("host: FAILED"), + "blank report adds no line: {blank}" ); - assert!(!blank.contains("host: FAILED"), "blank report adds no line: {blank}"); } // [unit->REQ-PUBLIC-ERROR-SURFACES] the JSON half of straggler (4): both LOCAL @@ -28952,9 +30007,14 @@ mod tests { let mut row = local_row(None); row.host_error = Some("adapter 'ghost' is not registered".to_string()); let json = serde_json::to_string(&row).unwrap(); - assert!(json.contains("\"host_error\":\"adapter 'ghost' is not registered\""), "{json}"); assert!( - !serde_json::to_string(&local_row(None)).unwrap().contains("\"host_error\""), + json.contains("\"host_error\":\"adapter 'ghost' is not registered\""), + "{json}" + ); + assert!( + !serde_json::to_string(&local_row(None)) + .unwrap() + .contains("\"host_error\""), "None omits the key" ); @@ -28971,13 +30031,20 @@ mod tests { host_error: Some("could not resume".to_string()), drop_dir: None, }; - assert!(serde_json::to_string(&pin).unwrap().contains("\"host_error\":\"could not resume\"")); - let clean = SelfPinJson { host_error: None, ..pin }; + assert!(serde_json::to_string(&pin) + .unwrap() + .contains("\"host_error\":\"could not resume\"")); + let clean = SelfPinJson { + host_error: None, + ..pin + }; // The QUOTED key, not a bare substring: `psyche_host_error` is always // serialized (no skip-if-none) and ends in `host_error`, so an unquoted // `contains` would pass on the sibling field and prove nothing. assert!( - !serde_json::to_string(&clean).unwrap().contains("\"host_error\""), + !serde_json::to_string(&clean) + .unwrap() + .contains("\"host_error\""), "None omits the key" ); } @@ -29095,7 +30162,8 @@ mod tests { assert!(matches!( parse(&["spt", "endpoint", "list", "--subnet", "home", "--detail"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Endpoint { action: Some(EndpointCmd::List { subnet: Some(_), @@ -29112,7 +30180,8 @@ mod tests { assert!(matches!( parse(&["spt", "endpoint", "rename", "ling", "oak"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Endpoint { action: Some(EndpointCmd::Rename { .. }) } @@ -29133,7 +30202,8 @@ mod tests { "work" ]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Endpoint { action: Some(EndpointCmd::Fork { delete_source: false, @@ -29147,26 +30217,38 @@ mod tests { ); // [unit->REQ-INST-3] the resting verbs (one local id). assert!(matches!( - parse(&["spt", "endpoint", "suspend", "ling"]).unwrap().cmd.unwrap(), + parse(&["spt", "endpoint", "suspend", "ling"]) + .unwrap() + .cmd + .unwrap(), Cmd::Endpoint { action: Some(EndpointCmd::Suspend { .. }) } )); assert!(matches!( - parse(&["spt", "endpoint", "wake", "ling"]).unwrap().cmd.unwrap(), + parse(&["spt", "endpoint", "wake", "ling"]) + .unwrap() + .cmd + .unwrap(), Cmd::Endpoint { action: Some(EndpointCmd::Wake { .. }) } )); // [unit->REQ-SHELL-2] shutdown with and without the self-default id. assert!(matches!( - parse(&["spt", "endpoint", "shutdown"]).unwrap().cmd.unwrap(), + parse(&["spt", "endpoint", "shutdown"]) + .unwrap() + .cmd + .unwrap(), Cmd::Endpoint { action: Some(EndpointCmd::Shutdown { id: None }) } )); assert!(matches!( - parse(&["spt", "endpoint", "stop", "bob"]).unwrap().cmd.unwrap(), + parse(&["spt", "endpoint", "stop", "bob"]) + .unwrap() + .cmd + .unwrap(), Cmd::Endpoint { action: Some(EndpointCmd::Stop { .. }) } @@ -29194,7 +30276,8 @@ mod tests { "ling" ]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Endpoint { action: Some(EndpointCmd::Description { action: Some(DescriptionCmd::Set { .. }) @@ -29202,7 +30285,10 @@ mod tests { } )); assert!(matches!( - parse(&["spt", "endpoint", "description"]).unwrap().cmd.unwrap(), + parse(&["spt", "endpoint", "description"]) + .unwrap() + .cmd + .unwrap(), Cmd::Endpoint { action: Some(EndpointCmd::Description { action: None }) } @@ -29315,7 +30401,10 @@ mod tests { "a one-subnet code is byte-compatible with every shipped reader — warning \ here would train the operator to ignore the line" ); - assert!(!warns(&[]), "and a legacy local-only code reaches no other node at all"); + assert!( + !warns(&[]), + "and a legacy local-only code reaches no other node at all" + ); // The warning names the ESCAPE, not just the problem: an operator told // only "this may not work" cannot act, and the narrowing spelling is the @@ -29402,8 +30491,8 @@ mod tests { "so the refusal lists what this node actually holds: {unknown}" ); - let partly_unknown = knock_code_subnet_choice(&many, &ask(&["home", "elsewhere"])) - .unwrap_err(); + let partly_unknown = + knock_code_subnet_choice(&many, &ask(&["home", "elsewhere"])).unwrap_err(); assert!( partly_unknown.starts_with("KNOCK_NO_SUCH_SUBNET:"), "ONE bad name refuses the WHOLE list rather than quietly sealing the good ones — \ @@ -29449,9 +30538,7 @@ mod tests { other => panic!("not a new-code: {other:?}"), } - match knock_route(&["spt", "knock", "new-code", "--surfaces", "MSG"]) - .expect("routes") - { + match knock_route(&["spt", "knock", "new-code", "--surfaces", "MSG"]).expect("routes") { KnockCmd::NewCode { admit_node, subnet, .. } => { @@ -30125,7 +31212,10 @@ mod tests { // `Local` is resolution's OWN answer that the target is on this node, so // it lands whatever the perch lookup says — asserted on the locality // value that would refuse a NotFound, so the two are not conflated. - assert_eq!(knock_landing(&O::Local, false), Some(KnockLanding::LocalInbox)); + assert_eq!( + knock_landing(&O::Local, false), + Some(KnockLanding::LocalInbox) + ); } // [unit->REQ-KNOCK-UNRESOLVED-REFUSES] THE NODE HALF: an addressed target is @@ -30479,7 +31569,14 @@ mod tests { for_endpoint, send_only, send_receive, - } => knock_route_bare(action, target, surfaces, for_endpoint, send_only, send_receive), + } => knock_route_bare( + action, + target, + surfaces, + for_endpoint, + send_only, + send_receive, + ), _ => panic!("not a knock"), } } @@ -30491,11 +31588,25 @@ mod tests { #[test] fn the_bare_form_is_the_send_form() { let bare = knock_route(&[ - "spt", "knock", "wanda", "--surfaces", "MSG,XFER", "--for", "e1", "--send-receive", + "spt", + "knock", + "wanda", + "--surfaces", + "MSG,XFER", + "--for", + "e1", + "--send-receive", ]) .expect("the bare form routes"); let explicit = knock_route(&[ - "spt", "knock", "send", "wanda", "--surfaces", "MSG,XFER", "--for", "e1", + "spt", + "knock", + "send", + "wanda", + "--surfaces", + "MSG,XFER", + "--for", + "e1", "--send-receive", ]) .expect("the explicit form routes"); @@ -30628,10 +31739,18 @@ mod tests { // the single-record flags rather than reinterpreting them, so the two // input shapes are never both live. assert!(matches!( - parse(&["spt", "endpoint", "monic", "add", "--batch"]).unwrap().cmd.unwrap(), + parse(&["spt", "endpoint", "monic", "add", "--batch"]) + .unwrap() + .cmd + .unwrap(), Cmd::Endpoint { action: Some(EndpointCmd::Monic { - action: Some(MonicCmd::Add { target: None, triggers: None, batch: true, .. }) + action: Some(MonicCmd::Add { + target: None, + triggers: None, + batch: true, + .. + }) }) } )); @@ -30727,7 +31846,11 @@ mod tests { #[test] fn the_kept_monic_suggestion_is_a_command_that_keeps_its_promise() { let s = kept_existing_suggestion("stranger"); - for marker in ["spt endpoint monic update", "--target stranger", "--triggers"] { + for marker in [ + "spt endpoint monic update", + "--target stranger", + "--triggers", + ] { assert!(s.contains(marker), "missing {marker}: {s}"); } assert!( @@ -30819,7 +31942,10 @@ mod tests { } )); assert!(matches!( - parse(&["spt", "daemon", "run", "--detached"]).unwrap().cmd.unwrap(), + parse(&["spt", "daemon", "run", "--detached"]) + .unwrap() + .cmd + .unwrap(), Cmd::Node { action: Some(DaemonCmd::Run { detached: true }) } @@ -30838,7 +31964,10 @@ mod tests { } )); assert!(matches!( - parse(&["spt", "daemon", "stop", "--force"]).unwrap().cmd.unwrap(), + parse(&["spt", "daemon", "stop", "--force"]) + .unwrap() + .cmd + .unwrap(), Cmd::Node { action: Some(DaemonCmd::Stop { force: true }) } @@ -30965,7 +32094,11 @@ mod tests { use std::cell::Cell; // Session already up ⇒ true on the first check, NO sleeps. let sleeps = Cell::new(0u32); - assert!(poll_until_ready(|| true, 5, || sleeps.set(sleeps.get() + 1))); + assert!(poll_until_ready( + || true, + 5, + || sleeps.set(sleeps.get() + 1) + )); assert_eq!(sleeps.get(), 0, "no sleep when the session is already up"); // No session ever ⇒ false (timeout): every attempt checked, slept between. @@ -30981,7 +32114,11 @@ mod tests { ); assert!(!out, "no session ⇒ timeout false"); assert_eq!(checks.get(), 4, "checked every attempt"); - assert_eq!(sleeps.get(), 3, "slept between attempts only (never after the last)"); + assert_eq!( + sleeps.get(), + 3, + "slept between attempts only (never after the last)" + ); // Session appears on a later attempt ⇒ true. let n = Cell::new(0u32); @@ -30993,7 +32130,11 @@ mod tests { 5, || {} )); - assert_eq!(n.get(), 3, "stopped polling the moment the session appeared"); + assert_eq!( + n.get(), + 3, + "stopped polling the moment the session appeared" + ); } // [unit->REQ-NOTIF-2] the notify/notif surfaces parse: `subnet notify` @@ -31013,7 +32154,8 @@ mod tests { "doyle" ]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Subnet { action: Some(SubnetCmd::Notify { .. }) } @@ -31027,13 +32169,17 @@ mod tests { assert!(matches!( parse(&["spt", "notif", "list", "--subnet", "home"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Notif { action: NotifCmd::List { .. } } )); assert!(matches!( - parse(&["spt", "notif", "dismiss", "cafe:7"]).unwrap().cmd.unwrap(), + parse(&["spt", "notif", "dismiss", "cafe:7"]) + .unwrap() + .cmd + .unwrap(), Cmd::Notif { action: NotifCmd::Dismiss { .. } } @@ -31076,8 +32222,12 @@ mod tests { // Explicit non-member target => refuse. assert!(resolve_notify_subnet(&store, Some("home".into()), None).is_err()); - store.create_subnet("home", spt_store::access::Mode::Open).unwrap(); - store.create_subnet("work", spt_store::access::Mode::Open).unwrap(); + store + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); + store + .create_subnet("work", spt_store::access::Mode::Open) + .unwrap(); // Explicit member target wins, home ignored. assert_eq!( resolve_notify_subnet(&store, Some("work".into()), Some("home".into())), @@ -31302,7 +32452,8 @@ mod tests { assert!(matches!( parse(&["spt", "grant", "add", "owner-shutdown", "ling"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Grant { action: GrantCmd::Add { qualifier: None, @@ -31313,7 +32464,8 @@ mod tests { assert!(matches!( parse(&["spt", "grant", "revoke", "spawn-shell", "ling"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Grant { action: GrantCmd::Revoke { .. } } @@ -31325,7 +32477,10 @@ mod tests { } )); assert!(matches!( - parse(&["spt", "grant", "list", "ling"]).unwrap().cmd.unwrap(), + parse(&["spt", "grant", "list", "ling"]) + .unwrap() + .cmd + .unwrap(), Cmd::Grant { action: GrantCmd::List { agent: Some(_) } } @@ -31417,7 +32572,8 @@ mod tests { assert!(matches!( parse(&["spt", "adapter", "add", "C:/adapters/mock"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Adapter { action: AdapterCmd::Add { path: Some(_), @@ -31430,7 +32586,8 @@ mod tests { assert!(matches!( parse(&["spt", "adapter", "add", "--github", "user/repo"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Adapter { action: AdapterCmd::Add { path: None, @@ -31443,9 +32600,18 @@ mod tests { // [unit->REQ-INSTALL-9] the release-archive source parses with its tag // and asset modifiers. assert!(matches!( - parse(&["spt", "adapter", "add", "--release", "user/repo", "--tag", "v1.0.0"]) - .unwrap() - .cmd.unwrap(), + parse(&[ + "spt", + "adapter", + "add", + "--release", + "user/repo", + "--tag", + "v1.0.0" + ]) + .unwrap() + .cmd + .unwrap(), Cmd::Adapter { action: AdapterCmd::Add { path: None, @@ -31459,7 +32625,7 @@ mod tests { match parse(&["spt", "adapter", "remove", "mock-shell", "--force"]) .unwrap() .cmd - .unwrap() + .unwrap() { Cmd::Adapter { action: AdapterCmd::Remove { name, force }, @@ -31475,13 +32641,26 @@ mod tests { action: AdapterCmd::List } )); - match parse(&["spt", "adapter", "create-profile", "claude-spt", "work", "--from", "o.toml"]) - .unwrap() - .cmd + match parse(&[ + "spt", + "adapter", + "create-profile", + "claude-spt", + "work", + "--from", + "o.toml", + ]) + .unwrap() + .cmd .unwrap() { Cmd::Adapter { - action: AdapterCmd::CreateProfile { adapter, name, from }, + action: + AdapterCmd::CreateProfile { + adapter, + name, + from, + }, } => { assert_eq!((adapter.as_str(), name.as_str()), ("claude-spt", "work")); assert_eq!(from.as_deref(), Some("o.toml")); @@ -31489,7 +32668,10 @@ mod tests { _ => panic!("expected Adapter CreateProfile"), } assert!(matches!( - parse(&["spt", "adapter", "delete-profile", "claude-spt", "work"]).unwrap().cmd.unwrap(), + parse(&["spt", "adapter", "delete-profile", "claude-spt", "work"]) + .unwrap() + .cmd + .unwrap(), Cmd::Adapter { action: AdapterCmd::DeleteProfile { .. } } @@ -31498,7 +32680,10 @@ mod tests { // `adapter` and nowhere else: a bare `spt service` must not parse, because // "service" already means the OS service manager hosting the daemon. assert!(matches!( - parse(&["spt", "adapter", "service", "list"]).unwrap().cmd.unwrap(), + parse(&["spt", "adapter", "service", "list"]) + .unwrap() + .cmd + .unwrap(), Cmd::Adapter { action: AdapterCmd::Service { action: AdapterServiceCmd::List @@ -31511,9 +32696,10 @@ mod tests { .unwrap() { Cmd::Adapter { - action: AdapterCmd::Service { - action: AdapterServiceCmd::Status { option }, - }, + action: + AdapterCmd::Service { + action: AdapterServiceCmd::Status { option }, + }, } => assert_eq!(option, "hub:staging"), _ => panic!("expected Adapter Service Status"), } @@ -31521,13 +32707,27 @@ mod tests { parse(&["spt", "service", "list"]).is_err(), "a bare `spt service` must not exist — the verb group is adapter-scoped" ); - match parse(&["spt", "adapter", "digest-proof", "claude-spt", "--sample", "log.jsonl"]) - .unwrap() - .cmd + match parse(&[ + "spt", + "adapter", + "digest-proof", + "claude-spt", + "--sample", + "log.jsonl", + ]) + .unwrap() + .cmd .unwrap() { Cmd::Adapter { - action: AdapterCmd::DigestProof { option, sample, session, dir, manifest }, + action: + AdapterCmd::DigestProof { + option, + sample, + session, + dir, + manifest, + }, } => { assert_eq!(option, "claude-spt"); assert_eq!(sample.as_deref(), Some("log.jsonl")); @@ -31562,7 +32762,14 @@ mod tests { spt_runtime::registry::register(&adapters, &d, 1).unwrap(); let proof = |sample: &std::path::Path| { - cmd_adapter_digest_proof(&adapters, "cc", Some(sample.to_str().unwrap()), None, None, None) + cmd_adapter_digest_proof( + &adapters, + "cc", + Some(sample.to_str().unwrap()), + None, + None, + None, + ) }; // A clean contract sample → proof passes. @@ -31591,7 +32798,14 @@ mod tests { std::fs::write(pd.join("manifest.toml"), nodig).unwrap(); spt_runtime::registry::register(&adapters, &pd, 1).unwrap(); assert_eq!( - cmd_adapter_digest_proof(&adapters, "plain", Some(good.to_str().unwrap()), None, None, None), + cmd_adapter_digest_proof( + &adapters, + "plain", + Some(good.to_str().unwrap()), + None, + None, + None + ), 2, "no [digest] section → exit 2" ); @@ -31634,13 +32848,27 @@ mod tests { // BEFORE F-004: this hard-failed with "no value for substitution key // {session_id}". Now the default placeholder resolves and the proof runs. assert_eq!( - cmd_adapter_digest_proof(&adapters, "cc", Some(good.to_str().unwrap()), None, None, None), + cmd_adapter_digest_proof( + &adapters, + "cc", + Some(good.to_str().unwrap()), + None, + None, + None + ), 0, "a session_id-templated extractor proofs with the default placeholder" ); // An explicit --session pins the id (same successful path). assert_eq!( - cmd_adapter_digest_proof(&adapters, "cc", Some(good.to_str().unwrap()), Some("sessA"), None, None), + cmd_adapter_digest_proof( + &adapters, + "cc", + Some(good.to_str().unwrap()), + Some("sessA"), + None, + None + ), 0, "--session pins the id and still proofs" ); @@ -31664,7 +32892,14 @@ mod tests { .unwrap() { Cmd::Adapter { - action: AdapterCmd::TranslateProof { option, event, session, dir, manifest }, + action: + AdapterCmd::TranslateProof { + option, + event, + session, + dir, + manifest, + }, } => { assert_eq!(option, "claude-spt"); assert_eq!(event, ""); @@ -31715,7 +32950,10 @@ mod tests { .parent() .and_then(|deps| deps.parent()) .expect("target profile dir"); - profile_dir.join(format!("translate_proof_fixture{}", std::env::consts::EXE_SUFFIX)) + profile_dir.join(format!( + "translate_proof_fixture{}", + std::env::consts::EXE_SUFFIX + )) } // [unit->REQ-ADAPTER-TRANSLATE-PROOF] translate-proof drives the REAL @@ -31804,37 +33042,54 @@ mod tests { spt_runtime::registry::register(&adapters, &d, 1).unwrap(); let create = |adapter: &str, name: &str, from: Option<&str>| { - cmd_adapter(AdapterCmd::CreateProfile { - adapter: adapter.into(), - name: name.into(), - from: from.map(str::to_string), - }, false) + cmd_adapter( + AdapterCmd::CreateProfile { + adapter: adapter.into(), + name: name.into(), + from: from.map(str::to_string), + }, + false, + ) }; // A tighten-only local overlay from a file: created. let overlay = spt_store::perch::spt_home().join("work.toml"); std::fs::write(&overlay, "[shell]\nrequire_approval = \"always\"\n").unwrap(); - assert_eq!(create("claude-spt", "work", Some(overlay.to_str().unwrap())), 0); + assert_eq!( + create("claude-spt", "work", Some(overlay.to_str().unwrap())), + 0 + ); assert_eq!( spt_runtime::registry::local_profile_names(&adapters, "claude-spt"), vec!["work"] ); // Shadowing a shipped name refuses; a floor-loosening overlay refuses. - assert_eq!(create("claude-spt", "locked", None), 1, "shipped-name shadow refused"); + assert_eq!( + create("claude-spt", "locked", None), + 1, + "shipped-name shadow refused" + ); let loose = spt_store::perch::spt_home().join("loose.toml"); std::fs::write(&loose, "[shell]\nrequire_approval = \"none\"\n").unwrap(); - assert_eq!(create("claude-spt", "loose", Some(loose.to_str().unwrap())), 1, "loosen refused"); + assert_eq!( + create("claude-spt", "loose", Some(loose.to_str().unwrap())), + 1, + "loosen refused" + ); // list renders adjacent (shipped + local) and returns 0. assert_eq!(cmd_adapter(AdapterCmd::List, false), 0); // delete-profile: a shipped name is immutable; the local is removed. let del = |name: &str| { - cmd_adapter(AdapterCmd::DeleteProfile { - adapter: "claude-spt".into(), - name: name.into(), - }, false) + cmd_adapter( + AdapterCmd::DeleteProfile { + adapter: "claude-spt".into(), + name: name.into(), + }, + false, + ) }; assert_eq!(del("locked"), 1, "shipped profile is immutable"); assert_eq!(del("work"), 0, "local removed"); @@ -31857,23 +33112,44 @@ mod tests { // `use` points the declared host binary at the adapter. assert_eq!( - cmd_adapter(AdapterCmd::Use { target: "claude-spt".into(), clear: false }, false), + cmd_adapter( + AdapterCmd::Use { + target: "claude-spt".into(), + clear: false + }, + false + ), 0 ); assert_eq!( - spt_runtime::resolve::load(&adapters).0.get("claude").map(String::as_str), + spt_runtime::resolve::load(&adapters) + .0 + .get("claude") + .map(String::as_str), Some("claude-spt") ); // An unregistered target fails — nothing pinned. assert_eq!( - cmd_adapter(AdapterCmd::Use { target: "ghost".into(), clear: false }, false), + cmd_adapter( + AdapterCmd::Use { + target: "ghost".into(), + clear: false + }, + false + ), 1 ); // `--clear` drops the pointer. assert_eq!( - cmd_adapter(AdapterCmd::Use { target: "claude-spt".into(), clear: true }, false), + cmd_adapter( + AdapterCmd::Use { + target: "claude-spt".into(), + clear: true + }, + false + ), 0 ); assert!(spt_runtime::resolve::load(&adapters).0.is_empty()); @@ -31894,14 +33170,23 @@ mod tests { spt_runtime::registry::register(&adapters, &d, 1).unwrap(); let get = |opt: &str, key: &str| { - cmd_adapter(AdapterCmd::GetString { option: opt.into(), key: key.into() }, false) + cmd_adapter( + AdapterCmd::GetString { + option: opt.into(), + key: key.into(), + }, + false, + ) }; let set = |opt: &str, key: &str, val: &str| { - cmd_adapter(AdapterCmd::SetString { - option: opt.into(), - key: key.into(), - value: val.into(), - }, false) + cmd_adapter( + AdapterCmd::SetString { + option: opt.into(), + key: key.into(), + value: val.into(), + }, + false, + ) }; // Read the base string (found = 0); a missing key = 1. @@ -31909,14 +33194,21 @@ mod tests { assert_eq!(get("claude-spt", "nope"), 1, "unset key exits 1"); // set-string needs a local target: a bare option is a usage error. - assert_eq!(set("claude-spt", "base", "x"), 2, "bare option has no local target"); + assert_eq!( + set("claude-spt", "base", "x"), + 2, + "bare option has no local target" + ); // Create a local profile, set a string into it, read it back composite. - cmd_adapter(AdapterCmd::CreateProfile { - adapter: "claude-spt".into(), - name: "work".into(), - from: None, - }, false); + cmd_adapter( + AdapterCmd::CreateProfile { + adapter: "claude-spt".into(), + name: "work".into(), + from: None, + }, + false, + ); assert_eq!(set("claude-spt:work", "base", "overridden"), 0); assert_eq!( spt_runtime::registry::get_string(&adapters, "claude-spt:work", "base") @@ -31960,7 +33252,10 @@ mod tests { _ => panic!("expected Shell Spawn"), } assert!(matches!( - parse(&["spt", "shell", "spawn", "GameRobot"]).unwrap().cmd.unwrap(), + parse(&["spt", "shell", "spawn", "GameRobot"]) + .unwrap() + .cmd + .unwrap(), Cmd::Shell { action: ShellCmd::Spawn { alias: None, @@ -31978,7 +33273,8 @@ mod tests { assert!(matches!( parse(&["spt", "shell", "teardown", "TempleKeeper"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Shell { action: ShellCmd::Teardown { .. } } @@ -31986,7 +33282,8 @@ mod tests { assert!(matches!( parse(&["spt", "shell", "rename", "GameRobot-0", "Keeper"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Shell { action: ShellCmd::Rename { .. } } @@ -31994,7 +33291,7 @@ mod tests { match parse(&["spt", "shell", "cmd", "TempleKeeper", "move", "north", "3"]) .unwrap() .cmd - .unwrap() + .unwrap() { Cmd::Shell { action: ShellCmd::Cmd { shell_ref, op, .. }, @@ -32009,7 +33306,8 @@ mod tests { assert!(matches!( parse(&["spt", "shell", "relink", "GameRobot-0"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Shell { action: ShellCmd::Relink { force: false, .. } } @@ -32017,17 +33315,26 @@ mod tests { assert!(matches!( parse(&["spt", "shell", "relink", "GameRobot-0", "--force"]) .unwrap() - .cmd.unwrap(), + .cmd + .unwrap(), Cmd::Shell { action: ShellCmd::Relink { force: true, .. } } )); // [unit->REQ-SHELL-3] drive parses the ref, the manifest-bounded type, // and the opaque payload; the type flag is required. - match parse(&["spt", "shell", "drive", "GameRobot-0", "--type", "stick", "x=0.7,y=-0.2"]) - .unwrap() - .cmd - .unwrap() + match parse(&[ + "spt", + "shell", + "drive", + "GameRobot-0", + "--type", + "stick", + "x=0.7,y=-0.2", + ]) + .unwrap() + .cmd + .unwrap() { Cmd::Shell { action: @@ -32071,7 +33378,10 @@ mod tests { _ => panic!("expected Shell Send"), } assert!(matches!( - parse(&["spt", "shell", "send", "Scout"]).unwrap().cmd.unwrap(), + parse(&["spt", "shell", "send", "Scout"]) + .unwrap() + .cmd + .unwrap(), Cmd::Shell { action: ShellCmd::Send { text: None, @@ -32101,11 +33411,14 @@ mod tests { let adapters = spt_store::perch::adapters_dir(); let spawn = |adapter: &str, alias: Option<&str>| { - cmd_shell(ShellCmd::Spawn { - adapter: adapter.into(), - alias: alias.map(str::to_string), - owner: Some("doyle".into()), - }, false) + cmd_shell( + ShellCmd::Spawn { + adapter: adapter.into(), + alias: alias.map(str::to_string), + owner: Some("doyle".into()), + }, + false, + ) }; // Nothing registered → refuse. @@ -32204,10 +33517,13 @@ mod tests { // Teardown frees the slot… assert_eq!( - cmd_shell(ShellCmd::Teardown { - shell_ref: "Toast".into(), - owner: Some("doyle".into()) - }, false), + cmd_shell( + ShellCmd::Teardown { + shell_ref: "Toast".into(), + owner: Some("doyle".into()) + }, + false + ), 0 ); assert_eq!(spawn("mock-shell", None), 0); @@ -32224,19 +33540,25 @@ mod tests { // resolve from the registered manifest, never the perch) — and the D4 // surface still refuses. assert_eq!( - cmd_shell(ShellCmd::Cmd { - shell_ref: "mock-shell-0".into(), - op: vec!["notify".into()], - owner: Some("doyle".into()), - }, false), + cmd_shell( + ShellCmd::Cmd { + shell_ref: "mock-shell-0".into(), + op: vec!["notify".into()], + owner: Some("doyle".into()), + }, + false + ), 1 ); assert_eq!( - cmd_shell(ShellCmd::Relink { - shell_ref: "mock-shell-0".into(), - owner: Some("doyle".into()), - force: false - }, false), + cmd_shell( + ShellCmd::Relink { + shell_ref: "mock-shell-0".into(), + owner: Some("doyle".into()), + force: false + }, + false + ), 1 ); } @@ -32266,11 +33588,14 @@ mod tests { spt_runtime::registry::register(&adapters, &src, 1).unwrap(); assert_eq!( - cmd_shell(ShellCmd::Spawn { - adapter: "mock-shell".into(), - alias: Some("Scout".into()), - owner: Some("doyle".into()), - }, false), + cmd_shell( + ShellCmd::Spawn { + adapter: "mock-shell".into(), + alias: Some("Scout".into()), + owner: Some("doyle".into()), + }, + false + ), 0 ); let shell_perch = perch::resolve_shell_perch_path_in(&owlery, "doyle", "mock-shell-0"); @@ -32278,11 +33603,14 @@ mod tests { spt_daemon::shellhost::read_link_token(&shell_perch).expect("spawn parked a token"); let relink = |shell_ref: &str, owner: &str| { - cmd_shell(ShellCmd::Relink { - shell_ref: shell_ref.into(), - owner: Some(owner.into()), - force: false, - }, false) + cmd_shell( + ShellCmd::Relink { + shell_ref: shell_ref.into(), + owner: Some(owner.into()), + force: false, + }, + false, + ) }; // Foreign owner resolves nothing; alias addressing works for the owner. @@ -32377,13 +33705,20 @@ mod tests { // held. Reading a stopped row here as proof the host is gone is exactly // the lie ADR-0045 forbids, so the verb must not write one. assert_eq!( - spt_store::info::read_info(&perch_path).unwrap().status.as_deref(), + spt_store::info::read_info(&perch_path) + .unwrap() + .status + .as_deref(), Some(spt_store::liveness::STATUS_ONLINE), "harness-hosted: the verb claims nothing about the harness's process" ); assert_eq!(cmd_shutdown(Some("ling".into())), 0, "idempotent (NO_EDGE)"); - assert_eq!(cmd_shutdown(None), 1, "no self resolvable outside a session"); + assert_eq!( + cmd_shutdown(None), + 1, + "no self resolvable outside a session" + ); assert_eq!( cmd_shutdown(Some("ling@node".into())), 1, @@ -32519,11 +33854,14 @@ mod tests { spt_runtime::registry::register(&adapters, &src, 1).unwrap(); } let spawn = |adapter: &str| { - cmd_shell(ShellCmd::Spawn { - adapter: adapter.into(), - alias: None, - owner: Some("doyle".into()), - }, false) + cmd_shell( + ShellCmd::Spawn { + adapter: adapter.into(), + alias: None, + owner: Some("doyle".into()), + }, + false, + ) }; assert_eq!(spawn("toast"), 0); assert_eq!(spawn("mute"), 0); @@ -32597,10 +33935,13 @@ mod tests { // Teardown retires the grant with the slot. assert_eq!( - cmd_shell(ShellCmd::Teardown { - shell_ref: "toast-0".into(), - owner: Some("doyle".into()) - }, false), + cmd_shell( + ShellCmd::Teardown { + shell_ref: "toast-0".into(), + owner: Some("doyle".into()) + }, + false + ), 0 ); assert!( @@ -32649,22 +33990,28 @@ mod tests { std::fs::write(owner_perch.join("info.json"), "{}").unwrap(); assert_eq!( - cmd_shell(ShellCmd::Spawn { - adapter: "mock-shell".into(), - alias: Some("Scout".into()), - owner: Some("doyle".into()), - }, false), + cmd_shell( + ShellCmd::Spawn { + adapter: "mock-shell".into(), + alias: Some("Scout".into()), + owner: Some("doyle".into()), + }, + false + ), 0 ); let shell_perch = perch::resolve_shell_perch_path_in(&owlery, "doyle", "mock-shell-0"); let token = spt_daemon::shellhost::read_link_token(&shell_perch).expect("token parked"); let key = spt_daemon::shellhost::link_key(&token); let cmd = |op: &[&str]| { - cmd_shell(ShellCmd::Cmd { - shell_ref: "Scout".into(), - op: op.iter().map(|s| s.to_string()).collect(), - owner: Some("doyle".into()), - }, false) + cmd_shell( + ShellCmd::Cmd { + shell_ref: "Scout".into(), + op: op.iter().map(|s| s.to_string()).collect(), + owner: Some("doyle".into()), + }, + false, + ) }; // Vocabulary bounds: unknown op + extra args refuse, nothing spooled. @@ -32693,12 +34040,15 @@ mod tests { let blob = spt_store::perch::spt_home().join("map.png"); std::fs::write(&blob, b"PNGDATA").unwrap(); assert_eq!( - cmd_shell(ShellCmd::Send { - shell_ref: "mock-shell-0".into(), - text: Some("hello shell".into()), - file: Some(blob), - owner: Some("doyle".into()), - }, false), + cmd_shell( + ShellCmd::Send { + shell_ref: "mock-shell-0".into(), + text: Some("hello shell".into()), + file: Some(blob), + owner: Some("doyle".into()), + }, + false + ), 0 ); let rows = spt_store::spool::peek_all_at(&shell_perch).unwrap(); @@ -32826,11 +34176,14 @@ mod tests { spt_store::nodeid::load_or_create().unwrap(); let owlery = perch::owlery_dir(); let spawn = |adapter: &str| { - cmd_shell(ShellCmd::Spawn { - adapter: adapter.into(), - alias: None, - owner: Some("doyle".into()), - }, false) + cmd_shell( + ShellCmd::Spawn { + adapter: adapter.into(), + alias: None, + owner: Some("doyle".into()), + }, + false, + ) }; // Two fit under the cap; the third refuses (every instance here is @@ -32842,10 +34195,13 @@ mod tests { assert_eq!(spawn("free"), 0); // Teardown frees the slot. assert_eq!( - cmd_shell(ShellCmd::Teardown { - shell_ref: "capped-0".into(), - owner: Some("doyle".into()) - }, false), + cmd_shell( + ShellCmd::Teardown { + shell_ref: "capped-0".into(), + owner: Some("doyle".into()) + }, + false + ), 0 ); assert_eq!(spawn("capped"), 0); @@ -32897,11 +34253,14 @@ mod tests { establish_owner("doyle"); let owlery = perch::owlery_dir(); let spawn = |adapter: &str| { - cmd_shell(ShellCmd::Spawn { - adapter: adapter.into(), - alias: None, - owner: Some("doyle".into()), - }, false) + cmd_shell( + ShellCmd::Spawn { + adapter: adapter.into(), + alias: None, + owner: Some("doyle".into()), + }, + false, + ) }; // Profiled spawn: succeeds, colon-free id, composite carried. @@ -32941,15 +34300,20 @@ mod tests { .to_hex(); // A member subnet gives the consent notif somewhere to live. let mut subnets = SubnetStore::load(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let owlery = perch::owlery_dir(); let spawn = |adapter: &str| { - cmd_shell(ShellCmd::Spawn { - adapter: adapter.into(), - alias: None, - owner: Some("doyle".into()), - }, false) + cmd_shell( + ShellCmd::Spawn { + adapter: adapter.into(), + alias: None, + owner: Some("doyle".into()), + }, + false, + ) }; // Ungranted, non-TTY: refused, nothing minted, the escalation notif @@ -33045,11 +34409,14 @@ mod tests { establish_owner("ling"); let owlery = perch::owlery_dir(); let spawn = |owner: &str, adapter: &str, alias: Option<&str>| { - cmd_shell(ShellCmd::Spawn { - adapter: adapter.into(), - alias: alias.map(str::to_string), - owner: Some(owner.into()), - }, false) + cmd_shell( + ShellCmd::Spawn { + adapter: adapter.into(), + alias: alias.map(str::to_string), + owner: Some(owner.into()), + }, + false, + ) }; assert_eq!(spawn("doyle", "mock-shell", Some("Scout")), 0); assert_eq!(spawn("ling", "other-shell", None), 0); @@ -33059,28 +34426,37 @@ mod tests { assert!(spt_store::shellinfo::resolve_shell_ref(&owlery, "ling", "mock-shell-0").is_none()); assert!(spt_store::shellinfo::resolve_shell_ref(&owlery, "ling", "Scout").is_none()); assert_eq!( - cmd_shell(ShellCmd::Cmd { - shell_ref: "mock-shell-0".into(), - op: vec!["notify".into()], - owner: Some("ling".into()), - }, false), + cmd_shell( + ShellCmd::Cmd { + shell_ref: "mock-shell-0".into(), + op: vec!["notify".into()], + owner: Some("ling".into()), + }, + false + ), 1, "a non-owner cannot drive the command channel" ); assert_eq!( - cmd_shell(ShellCmd::Teardown { - shell_ref: "Scout".into(), - owner: Some("ling".into()) - }, false), + cmd_shell( + ShellCmd::Teardown { + shell_ref: "Scout".into(), + owner: Some("ling".into()) + }, + false + ), 1, "a non-owner cannot tear down" ); assert_eq!( - cmd_shell(ShellCmd::Rename { - shell_ref: "mock-shell-0".into(), - alias: "Stolen".into(), - owner: Some("ling".into()), - }, false), + cmd_shell( + ShellCmd::Rename { + shell_ref: "mock-shell-0".into(), + alias: "Stolen".into(), + owner: Some("ling".into()), + }, + false + ), 1, "a non-owner cannot rename" ); @@ -33182,8 +34558,16 @@ mod tests { // Cursor 150 sits inside the window (floor 100 <= 150) → not a predate. let (shown, predates) = filter_after(&digest, 150); assert!(!predates, "cursor inside the window does not predate it"); - let inputs: Vec<_> = shown.turns.iter().filter_map(|t| t.input.as_deref()).collect(); - assert_eq!(inputs, vec!["new"], "only the turn newer than the cursor survives"); + let inputs: Vec<_> = shown + .turns + .iter() + .filter_map(|t| t.input.as_deref()) + .collect(); + assert_eq!( + inputs, + vec!["new"], + "only the turn newer than the cursor survives" + ); } // [unit->REQ-DIGEST-CURSOR] a cursor BELOW the window's lowest committed seq @@ -33207,7 +34591,11 @@ mod tests { // Cursor 10 is below the window floor (500) → predates. let (shown, predates) = filter_after(&digest, 10); assert!(predates, "a cursor below the window floor predates it"); - assert_eq!(shown.turns.len(), 1, "the FULL window is returned, not empty"); + assert_eq!( + shown.turns.len(), + 1, + "the FULL window is returned, not empty" + ); // The JSON form carries the after_predates_window signal. let (json, _) = digest_snapshot_output(&shown, predates, 7, true, "ep"); assert!( @@ -33258,8 +34646,16 @@ mod tests { // Poll just below the sealed turn: exactly that turn comes back. let (shown, predates) = filter_after(&remote_reply, 59); assert!(!predates, "a cursor inside the window is not a predate"); - let inputs: Vec<_> = shown.turns.iter().filter_map(|t| t.input.as_deref()).collect(); - assert_eq!(inputs, vec!["tag this release"], "only rows past the cursor"); + let inputs: Vec<_> = shown + .turns + .iter() + .filter_map(|t| t.input.as_deref()) + .collect(); + assert_eq!( + inputs, + vec!["tag this release"], + "only rows past the cursor" + ); // Poll AT the sealed turn's newest seq: nothing new — the incremental poll // terminates instead of re-reading the same turn forever. @@ -33335,7 +34731,10 @@ mod tests { v.get("after_predates_window").is_none(), "no spurious predates signal when the cursor did not predate" ); - assert!(err.is_empty(), "--json leaves stderr clean (no DIGEST: trailer): {err:?}"); + assert!( + err.is_empty(), + "--json leaves stderr clean (no DIGEST: trailer): {err:?}" + ); } // [unit->REQ-DIGEST-JSON-SELF-CONTAINED] the human (non-json) path keeps @@ -33367,7 +34766,10 @@ mod tests { v.get("after_predates_window").and_then(|x| x.as_bool()), Some(true) ); - assert!(err.is_empty(), "--json stays stderr-clean on the predates path too"); + assert!( + err.is_empty(), + "--json stays stderr-clean on the predates path too" + ); } // [unit->REQ-MSG-2] [unit->REQ-RING-TIMEOUT-MINUTES] ring timeout defaults to @@ -33525,8 +34927,12 @@ mod tests { let _h = crate::testutil::isolated_home(); let mut subnets = SubnetStore::load(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); - subnets.create_subnet("work", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); + subnets + .create_subnet("work", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let src_perch = perch::resolve_perch_path("ling", ParentHint::Infer); @@ -33685,11 +35091,19 @@ mod tests { // postures and have one silently win. assert!(matches!( subnet_cmd(&["spt", "subnet", "create", "home", "--open"]), - Some(SubnetCmd::Create { open: true, closed: false, .. }) + Some(SubnetCmd::Create { + open: true, + closed: false, + .. + }) )); assert!(matches!( subnet_cmd(&["spt", "subnet", "create", "home", "--closed"]), - Some(SubnetCmd::Create { open: false, closed: true, .. }) + Some(SubnetCmd::Create { + open: false, + closed: true, + .. + }) )); assert!( parse(&["spt", "subnet", "create", "home", "--open", "--closed"]).is_err(), @@ -33910,7 +35324,11 @@ mod tests { let mut store = SubnetStore::default(); let now = 1_111_111_109; let r = decide_create( - resolve(&mut store, None, Some(("home".into(), spt_store::access::Mode::Open))), + resolve( + &mut store, + None, + Some(("home".into(), spt_store::access::Mode::Open)), + ), now, Elevation::Elevated, ); @@ -33972,7 +35390,11 @@ mod tests { fn create_not_elevated_refuses_without_saving() { let mut store = SubnetStore::default(); let r = decide_create( - resolve(&mut store, None, Some(("home".into(), spt_store::access::Mode::Open))), + resolve( + &mut store, + None, + Some(("home".into(), spt_store::access::Mode::Open)), + ), 0, Elevation::NotElevated, ); @@ -33988,7 +35410,11 @@ mod tests { fn create_existing_name_is_usage_error() { let mut store = store_with(&["home"]); let r = decide_create( - resolve(&mut store, None, Some(("home".into(), spt_store::access::Mode::Open))), + resolve( + &mut store, + None, + Some(("home".into(), spt_store::access::Mode::Open)), + ), 0, Elevation::Elevated, ); @@ -34117,7 +35543,10 @@ mod tests { // [unit->REQ-SUBNET-REVOKE-ADMIN-GATE] for s in [step - 1, step, step + 1] { let code = format!("{:06}", totp.code_at_step(s, 6)); - assert!(capture_proof_matches(admin_seed, &code, now), "window step {s}"); + assert!( + capture_proof_matches(admin_seed, &code, now), + "window step {s}" + ); } for s in [step - 2, step + 2] { let code = format!("{:06}", totp.code_at_step(s, 6)); @@ -34126,21 +35555,24 @@ mod tests { "outside the window must refuse (step {s})" ); } - assert!(!capture_proof_matches(admin_seed, "000000", now) || { - // A one-in-a-million collision with a window code is possible in - // principle; assert against the actual window set instead of luck. - let window: Vec = [step - 1, step, step + 1] - .iter() - .map(|s| format!("{:06}", totp.code_at_step(*s, 6))) - .collect(); - window.contains(&"000000".to_string()) - }); + assert!( + !capture_proof_matches(admin_seed, "000000", now) || { + // A one-in-a-million collision with a window code is possible in + // principle; assert against the actual window set instead of luck. + let window: Vec = [step - 1, step, step + 1] + .iter() + .map(|s| format!("{:06}", totp.code_at_step(*s, 6))) + .collect(); + window.contains(&"000000".to_string()) + } + ); // A SECOND authenticator entry: its own account label, so scanning it // adds an entry rather than overwriting the member key's — carried by // the capture phase, where the admin material now lives. - let admin_uri = - TotpSeed::from_bytes(rec.admin_seed_bytes().unwrap()).otpauth_uri(ISSUER, &admin_account("home")); - let member_uri = TotpSeed::from_bytes(rec.seed_bytes().unwrap()).otpauth_uri(ISSUER, "home"); + let admin_uri = TotpSeed::from_bytes(rec.admin_seed_bytes().unwrap()) + .otpauth_uri(ISSUER, &admin_account("home")); + let member_uri = + TotpSeed::from_bytes(rec.seed_bytes().unwrap()).otpauth_uri(ISSUER, "home"); assert_ne!(admin_uri, member_uri, "distinct authenticator entries"); assert!( phase.contains(&admin_uri), @@ -34158,7 +35590,10 @@ mod tests { !shown.to_ascii_lowercase().contains("admin"), "show-code names no admin material at all: {shown}" ); - assert!(shown.contains(&member_b32), "member re-provision unaffected"); + assert!( + shown.contains(&member_b32), + "member re-provision unaffected" + ); } // [unit->REQ-SUBNET-DUAL-SEED-MINT] the mode question has NO preselection: @@ -34186,7 +35621,14 @@ mod tests { ModeChoice::Chosen(Mode::Closed) ); // No answer, an empty line, and a typo all refuse rather than pick. - for answer in [None, Some(""), Some(" "), Some("y"), Some("safe"), Some("o")] { + for answer in [ + None, + Some(""), + Some(" "), + Some("y"), + Some("safe"), + Some("o"), + ] { assert_eq!( decide_create_mode(false, false, answer), ModeChoice::Unstated, @@ -34247,7 +35689,10 @@ mod tests { // sites route it through helpfmt::render — so STRIP mode (a piped adapter) // yields zero backticks / zero ANSI while the human words survive. // [unit->REQ-CLI-OUTPUT-MARKDOWN] - assert!(HINT_FOOTER.contains('`'), "the hint footer authors backticks"); + assert!( + HINT_FOOTER.contains('`'), + "the hint footer authors backticks" + ); let stripped = crate::helpfmt::render(&empty, false); assert!( !stripped.contains('`'), @@ -34302,8 +35747,7 @@ mod tests { // the two row-nodes = 4. let mut member_roster = spt_store::roster::RosterStore::default(); member_roster.upsert_self("home", "dd", "", "", None, "0", 1); - let rows = - subnet_status_rows(&store, &access, ®s, &member_roster, Some("cc"), None); + let rows = subnet_status_rows(&store, &access, ®s, &member_roster, Some("cc"), None); assert_eq!( (rows[0].nodes, rows[0].endpoints), (4, 3), @@ -34650,7 +36094,10 @@ mod tests { let mismatch = install_platform_check("x86_64-unknown-linux-gnu", Some("aarch64")); assert!(mismatch.is_err(), "a host-arch disagreement must refuse"); let unprobed = install_platform_check("x86_64-unknown-linux-gnu", None); - assert!(unprobed.is_ok(), "an unprobeable host keeps the registry leg only"); + assert!( + unprobed.is_ok(), + "an unprobeable host keeps the registry leg only" + ); } // [unit->REQ-INSTALL-BOOTSTRAP-VERB] placement is idempotent: a fresh @@ -34804,8 +36251,14 @@ mod tests { #[test] fn finish_message_states_fully_live_no_manual_restart() { let fresh = render_finish_message(9, "0.29.0", false); - assert!(fresh.contains("Updated spt-core to v0.29.0"), "head: {fresh}"); - assert!(fresh.contains("fully live"), "states the node runs it: {fresh}"); + assert!( + fresh.contains("Updated spt-core to v0.29.0"), + "head: {fresh}" + ); + assert!( + fresh.contains("fully live"), + "states the node runs it: {fresh}" + ); let already = render_finish_message(9, "0.29.0", true); assert!( already.contains("already installed"), @@ -34846,7 +36299,10 @@ mod tests { let stale = render_broker_image_line(Some("0.19.1"), "0.20.0"); assert!(stale.contains("0.19.1"), "names the running image: {stale}"); - assert!(stale.contains("0.20.0"), "names the installed version: {stale}"); + assert!( + stale.contains("0.20.0"), + "names the installed version: {stale}" + ); let too_old = render_broker_image_line(None, "0.20.0"); assert!( @@ -34900,7 +36356,10 @@ mod tests { let stale = render_coordinator_image_line(Some("0.19.1"), "0.20.0"); assert!(stale.contains("0.19.1"), "names the running image: {stale}"); - assert!(stale.contains("0.20.0"), "names the installed version: {stale}"); + assert!( + stale.contains("0.20.0"), + "names the installed version: {stale}" + ); assert!( stale.contains("spt node refresh"), "gives the in-place remedy: {stale}" @@ -34916,8 +36375,7 @@ mod tests { "states it is unknown: {unreported}" ); assert!( - !unreported.to_lowercase().contains("refresh") - && !unreported.contains("spt node stop"), + !unreported.to_lowercase().contains("refresh") && !unreported.contains("spt node stop"), "an unreported coordinator is not evidence of staleness — no remedy: {unreported}" ); @@ -34961,14 +36419,18 @@ mod tests { fn stall_evict_line_surfaces_only_a_real_tally() { assert_eq!(render_stall_evict_line(None), None, "unqueryable → no line"); - let healthy = render_stall_evict_line(Some((0, 0))).expect("Some(0) renders a healthy line"); + let healthy = + render_stall_evict_line(Some((0, 0))).expect("Some(0) renders a healthy line"); assert!(healthy.contains("healthy"), "got {healthy}"); assert!(healthy.contains("none"), "got {healthy}"); - let evicted = - render_stall_evict_line(Some((3, 1_700_000_000_000))).expect("a non-zero tally renders"); + let evicted = render_stall_evict_line(Some((3, 1_700_000_000_000))) + .expect("a non-zero tally renders"); assert!(evicted.contains('3'), "names the count: {evicted}"); - assert!(evicted.contains("1700000000000"), "names the last time: {evicted}"); + assert!( + evicted.contains("1700000000000"), + "names the last time: {evicted}" + ); assert!( evicted.to_lowercase().contains("reattach") || evicted.to_lowercase().contains("take"), "explains control was released: {evicted}" @@ -34994,11 +36456,19 @@ mod tests { use spt_daemon::pump::health::PumpHealth; let now = 1_700_000_100_000u64; - assert_eq!(render_peer_health_line(None, now), None, "no snapshot → no line"); + assert_eq!( + render_peer_health_line(None, now), + None, + "no snapshot → no line" + ); let mut solo = PumpHealth::default(); solo.set_targets(Vec::::new(), 0); - assert_eq!(render_peer_health_line(Some(&solo), now), None, "solo node → silent"); + assert_eq!( + render_peer_health_line(Some(&solo), now), + None, + "solo node → silent" + ); assert_eq!(peer_health_verdict_token(&solo), "idle"); // The sequester fingerprint: all targets failing, nothing live. @@ -35020,9 +36490,18 @@ mod tests { h.note_connected("a", ["a"], 1_700_000_090_000); let partial = render_peer_health_line(Some(&h), now).expect("degraded-partial renders"); assert!(partial.contains("DEGRADED (partial)"), "got {partial}"); - assert!(partial.contains("1 of 2"), "names the unreachable count: {partial}"); - assert!(partial.contains("quic-connect"), "keeps the stage: {partial}"); - assert!(!partial.contains("healthy"), "never reads healthy: {partial}"); + assert!( + partial.contains("1 of 2"), + "names the unreachable count: {partial}" + ); + assert!( + partial.contains("quic-connect"), + "keeps the stage: {partial}" + ); + assert!( + !partial.contains("healthy"), + "never reads healthy: {partial}" + ); assert_eq!(peer_health_verdict_token(&h), "degraded-partial"); // Green needs real progress on EVERY target — the original intent, @@ -35035,7 +36514,10 @@ mod tests { // Public wording only. for line in [&partial, &line] { assert!(!line.contains("REQ-"), "no internal req tag: {line}"); - assert!(!line.contains("PUMP_PEER_FAIL"), "no internal CODE marker: {line}"); + assert!( + !line.contains("PUMP_PEER_FAIL"), + "no internal CODE marker: {line}" + ); } } @@ -35069,14 +36551,23 @@ mod tests { assert!(line.contains("peers unreachable:"), "got {line}"); assert!(line.contains("1 of 2"), "names how many are absent: {line}"); assert!(line.contains("quic-connect"), "keeps the stage: {line}"); - assert!(line.contains("1/2 connected"), "still reports the live count: {line}"); + assert!( + line.contains("1/2 connected"), + "still reports the live count: {line}" + ); assert!(!line.contains("healthy"), "never reads healthy: {line}"); - assert!(!line.contains("DEGRADED"), "and never blames this node: {line}"); + assert!( + !line.contains("DEGRADED"), + "and never blames this node: {line}" + ); assert_eq!(peer_health_verdict_token(&h), "peers-absent"); // Public wording only — no internal codes leak into the new sentence. assert!(!line.contains("REQ-"), "no internal req tag: {line}"); - assert!(!line.contains("PUMP_PEER_FAIL"), "no internal CODE marker: {line}"); + assert!( + !line.contains("PUMP_PEER_FAIL"), + "no internal CODE marker: {line}" + ); } // [unit->REQ-PEER-COUNT-TARGET-SCOPED] THE RENDERED FRACTION, at the @@ -35092,7 +36583,11 @@ mod tests { let mut h = PumpHealth::default(); h.set_targets((1..=7).map(|i| format!("p{i}")), 1_700_000_000_000); for i in 1..=7 { - h.note_connected(&format!("p{i}"), (1..=i).map(|j| format!("p{j}")), 1_700_000_010_000); + h.note_connected( + &format!("p{i}"), + (1..=i).map(|j| format!("p{j}")), + 1_700_000_010_000, + ); } let line = render_peer_health_line(Some(&h), now).expect("healthy renders"); assert!(line.contains("7/7 peers connected"), "got {line}"); @@ -35101,8 +36596,14 @@ mod tests { // read over the one target that remains, never `7/1`. h.set_targets(["p1".to_string()], 1_700_000_020_000); let line = render_peer_health_line(Some(&h), now).expect("healthy renders"); - assert!(line.contains("1/1 peers connected"), "the pre-fix line read 7/1: {line}"); - assert!(!line.contains("7/1"), "the field specimen must be unreachable: {line}"); + assert!( + line.contains("1/1 peers connected"), + "the pre-fix line read 7/1: {line}" + ); + assert!( + !line.contains("7/1"), + "the field specimen must be unreachable: {line}" + ); } /// A `subnet status --json` payload carrying `verdict` and nothing else of @@ -35220,11 +36721,7 @@ mod tests { } #[cfg(test)] - fn knock_fixture( - knocker: &str, - surfaces: &[&str], - as_user: bool, - ) -> spt_store::knock::Knock { + fn knock_fixture(knocker: &str, surfaces: &[&str], as_user: bool) -> spt_store::knock::Knock { spt_store::knock::Knock::stamped( "k-test", knocker, @@ -35238,7 +36735,6 @@ mod tests { ) } - /// Render one site's `--help` from the SAME wiring the binary uses. fn rendered_help_at(path: &[&str]) -> String { use clap::CommandFactory; @@ -35486,8 +36982,14 @@ mod tests { assert!(retired_access_verb("rules").is_some()); assert!(retired_access_verb("LIST").is_some(), "case-folded"); assert!(retired_access_verb("Rules").is_some(), "case-folded"); - assert!(retired_access_verb("allow").is_none(), "a LIVE verb is not retired"); - assert!(retired_access_verb("ling").is_none(), "an ordinary endpoint id"); + assert!( + retired_access_verb("allow").is_none(), + "a LIVE verb is not retired" + ); + assert!( + retired_access_verb("ling").is_none(), + "an ordinary endpoint id" + ); let _home = crate::testutil::isolated_home(); @@ -35565,7 +37067,9 @@ mod tests { provenance: Provenance::Manual, decision, }; - let node = || Subject::Node { node: "aa11".into() }; + let node = || Subject::Node { + node: "aa11".into(), + }; let fork_only = rule(&[surface::FORK], RuleDecision::Allow, node()); // A blanket-closed node: post-releases#180 it does NOT refuse DISCOVER, @@ -35593,7 +37097,11 @@ mod tests { for (label, r) in [ ( "a grant that already names the pair", - rule(&[surface::FORK, surface::DISCOVER], RuleDecision::Allow, node()), + rule( + &[surface::FORK, surface::DISCOVER], + RuleDecision::Allow, + node(), + ), ), ( "a blanket grant, which covers DISCOVER by definition", @@ -35671,7 +37179,9 @@ mod tests { // One member is denied DISCOVER by name; the other is not. let mut store = AccessStore::default(); store.node.rules.push(AccessRule { - subject: Subject::Node { node: "aa11".into() }, + subject: Subject::Node { + node: "aa11".into(), + }, surfaces: vec![surface::DISCOVER.to_string()], origin: OriginQualifier::Any, provenance: Provenance::Manual, @@ -35683,7 +37193,9 @@ mod tests { &store, "ling", &AccessRule { - subject: Subject::SubnetWildcard { subnet: "work".into() }, + subject: Subject::SubnetWildcard { + subnet: "work".into(), + }, surfaces: vec![surface::FORK.to_string()], origin: OriginQualifier::Any, provenance: Provenance::Manual, @@ -35798,14 +37310,18 @@ mod tests { let subnets = spt_store::subnet::SubnetStore::default(); let aa11 = || GrantOrigins::Concrete(vec!["aa11".to_string()]); let rule = |surfaces: &[&str], origin| AccessRule { - subject: Subject::Node { node: "aa11".into() }, + subject: Subject::Node { + node: "aa11".into(), + }, surfaces: surfaces.iter().map(|s| s.to_string()).collect(), origin, provenance: Provenance::Manual, decision: RuleDecision::Allow, }; let deny = |surfaces: &[&str], origin| AccessRule { - subject: Subject::Node { node: "aa11".into() }, + subject: Subject::Node { + node: "aa11".into(), + }, surfaces: surfaces.iter().map(|s| s.to_string()).collect(), origin, provenance: Provenance::Manual, @@ -35872,7 +37388,14 @@ mod tests { .rules .push(deny(&[surface::MSG], OriginQualifier::User)); assert_eq!( - inert_grant_with(&users_closed, "ling", &msg_grant, &aa11(), &roster, &subnets), + inert_grant_with( + &users_closed, + "ling", + &msg_grant, + &aa11(), + &roster, + &subnets + ), None, "an unqualified grant admits both classes, and one of them is refused today" ); @@ -35985,7 +37508,10 @@ mod tests { // ask" into "asked everyone, all allowed". for (label, origins) in [ ("the named absence", origins), - ("an empty concrete population", GrantOrigins::Concrete(vec![])), + ( + "an empty concrete population", + GrantOrigins::Concrete(vec![]), + ), ] { let verdict = inert_grant_with( &AccessStore::default(), @@ -36105,9 +37631,7 @@ mod tests { // engine-room target. #[test] fn the_conjunction_notice_fires_per_missing_half_and_stays_silent_when_both_hold() { - use spt_store::access::{ - AccessRule, OriginQualifier, Provenance, RuleDecision, Subject, - }; + use spt_store::access::{AccessRule, OriginQualifier, Provenance, RuleDecision, Subject}; use spt_store::engineroom::Posture; let rule = |decision, subject, surfaces: &[&str]| AccessRule { @@ -36211,7 +37735,11 @@ mod tests { assert_eq!( classify_er_discover_conjunction( true, - &rule(RuleDecision::Allow, node("aa11"), &[spt_store::access::surface::MSG]), + &rule( + RuleDecision::Allow, + node("aa11"), + &[spt_store::access::surface::MSG] + ), &[], Posture::Online ), @@ -36226,7 +37754,9 @@ mod tests { true, &rule( RuleDecision::Allow, - Subject::SubnetWildcard { subnet: "spt-dev".into() }, + Subject::SubnetWildcard { + subnet: "spt-dev".into() + }, &discover ), &["bb22".to_string()], @@ -36338,8 +37868,7 @@ mod tests { #[test] fn the_conjunction_notice_names_the_whitelist_its_seat_and_the_posture() { use spt_store::engineroom::Posture; - let empty = - er_discover_conjunction_notice(&ErDiscoverGap::WhitelistEmpty, Posture::Online); + let empty = er_discover_conjunction_notice(&ErDiscoverGap::WhitelistEmpty, Posture::Online); assert!(empty.starts_with("ER_DISCOVER_CONJUNCTION:")); assert!( empty.contains("the rule landed and is in force"), @@ -36514,7 +38043,10 @@ mod tests { // …and the help carries the same rows under its own heading, so the two // renderings differ by a heading and by nothing else. let composed = spt_store::access::surface::control_surfaces(); - assert!(composed.contains(&rows), "the help lost the shared rows:\n{composed}"); + assert!( + composed.contains(&rows), + "the help lost the shared rows:\n{composed}" + ); let briefing = spt_store::briefing::compose_briefing(&spt_store::briefing::BriefingFacts::default()); @@ -37051,8 +38583,10 @@ mod tests { has_internal_code("see REQ-ACL-SURFACE-DESCRIPTION for why"), "the predicate must be able to fail, or its green means nothing" ); - assert!(!has_internal_code("Control surfaces: - MSG — direct messages")); + assert!(!has_internal_code( + "Control surfaces: + MSG — direct messages" + )); // (a) the walk covers exactly the ruled set — not fewer. let mut visited = 0usize; @@ -37318,7 +38852,10 @@ mod tests { // NOT SIMPLY ALWAYS REFUSING. Three ways to be quiet, and the third is // the one a naive scan gets wrong: a retired spelling sitting INSIDE a // flag's value is a word in a note, not a flag the operator typed. - assert_eq!(retired(&["spt", "knock", "send", "wanda", "--send-only"]), None); + assert_eq!( + retired(&["spt", "knock", "send", "wanda", "--send-only"]), + None + ); assert_eq!(retired(&["spt", "send", "doyle", "--mutual"]), None); assert_eq!( retired(&[ @@ -37411,7 +38948,12 @@ mod tests { "with the reason it actually got: {failed}" ); - let silent = answer_receipt_undelivered("doyle", &A::Unconfirmed { node: "aa11bb22".into() }); + let silent = answer_receipt_undelivered( + "doyle", + &A::Unconfirmed { + node: "aa11bb22".into(), + }, + ); assert!( silent.contains("gave no answer"), "silence reads as nothing known, not as a refusal: {silent}" @@ -37446,7 +38988,11 @@ mod tests { use spt_store::access::surface; let two_way = approve_directionality_lines(true, "alpha", "wanda", &[]); - assert_eq!(two_way.len(), 1, "the two-way branch has no remedy to offer"); + assert_eq!( + two_way.len(), + 1, + "the two-way branch has no remedy to offer" + ); assert!( two_way[0].contains("TWO-way") && two_way[0].contains("alpha"), "{two_way:?}" @@ -37737,7 +39283,8 @@ mod tests { // takes it out of widening. Replaced rather than annotated — a // stale row is read before the note explaining it. Case { - why: "a HUMAN knocker's attributable surface binds humans only, so no acknowledgment", + why: + "a HUMAN knocker's attributable surface binds humans only, so no acknowledgment", store: &permissive, knock: knock_fixture("aa11bb22", &[surface::MSG], true), granting: &msg, @@ -37767,7 +39314,15 @@ mod tests { }, ]; - for Case { why, store, knock, granting, authority, want } in cases { + for Case { + why, + store, + knock, + granting, + authority, + want, + } in cases + { assert_eq!( approval_form(store, &knock, granting, authority), want, @@ -37796,7 +39351,9 @@ mod tests { let pk = spt_proto::identity::Identity::from_seed(&[7u8; 32]).public_key(); let id = EndpointId::from_bytes(&pk.to_bytes()).expect("valid ed25519 point"); - let relay: RelayUrl = "https://relay.example.invalid./".parse().expect("relay url"); + let relay: RelayUrl = "https://relay.example.invalid./" + .parse() + .expect("relay url"); // The real fleet shape: homed on a relay, with direct paths beside it. let homed = serde_json::to_value( @@ -37811,7 +39368,10 @@ mod tests { line.contains(&relay.to_string()), "names the relay we are ACTUALLY homed on (not the configured one): {line}" ); - assert!(line.contains('2'), "counts the direct paths beside the relay: {line}"); + assert!( + line.contains('2'), + "counts the direct paths beside the relay: {line}" + ); // Relay-less: a real, reported state — a LINE that says so, never an // absent line an operator would read as "not measured". @@ -37820,11 +39380,21 @@ mod tests { ) .unwrap(); let none = render_self_endpoint_line(Some(&direct_only)).expect("relay-less still renders"); - assert!(none.to_lowercase().contains("no relay"), "says so out loud: {none}"); - assert!(!none.contains("https://"), "and names no relay it does not have: {none}"); + assert!( + none.to_lowercase().contains("no relay"), + "says so out loud: {none}" + ); + assert!( + !none.contains("https://"), + "and names no relay it does not have: {none}" + ); // Nothing to ask (daemon down / net-less broker) is the ONLY silence. - assert_eq!(render_self_endpoint_line(None), None, "no endpoint → no line"); + assert_eq!( + render_self_endpoint_line(None), + None, + "no endpoint → no line" + ); assert_eq!( render_self_endpoint_line(Some(&serde_json::Value::Null)), None, @@ -37867,12 +39437,21 @@ mod tests { stats.last_cycle.tree_scans = 2; let fresh = render_project_index_line(Some(&stats)).expect("stats render"); assert!(fresh.contains("fresh"), "got {fresh}"); - assert!(fresh.contains("3 endpoint(s)") && fresh.contains("2 project(s)"), "got {fresh}"); - assert!(fresh.contains("1 branch enum") && fresh.contains("2 tree scan"), "got {fresh}"); + assert!( + fresh.contains("3 endpoint(s)") && fresh.contains("2 project(s)"), + "got {fresh}" + ); + assert!( + fresh.contains("1 branch enum") && fresh.contains("2 tree scan"), + "got {fresh}" + ); stats.last_error = Some("branch enumeration: boom".to_string()); let failed = render_project_index_line(Some(&stats)).expect("failure renders"); - assert!(failed.contains("last-known-good"), "degradation is stated: {failed}"); + assert!( + failed.contains("last-known-good"), + "degradation is stated: {failed}" + ); for line in [&fresh, &failed] { assert!(!line.contains("REQ-"), "no internal req tag: {line}"); @@ -37885,7 +39464,10 @@ mod tests { #[test] fn stop_guard_refuses_live_sessions_without_force() { // No hosted sessions → proceed regardless of force. - assert!(stop_live_session_guard(&[], false).is_ok(), "nothing hosted → stop"); + assert!( + stop_live_session_guard(&[], false).is_ok(), + "nothing hosted → stop" + ); assert!(stop_live_session_guard(&[], true).is_ok()); // --force proceeds even with live sessions. assert!( @@ -37895,9 +39477,15 @@ mod tests { // Live sessions, no --force → refuse + name them + point at --force. let err = stop_live_session_guard(&["doyle".into(), "perri".into()], false) .expect_err("live sessions without --force must refuse"); - assert!(err.contains("doyle") && err.contains("perri"), "names the sessions: {err}"); + assert!( + err.contains("doyle") && err.contains("perri"), + "names the sessions: {err}" + ); assert!(err.contains("--force"), "points at the override: {err}"); - assert!(err.contains("come back"), "reassures they survive a restart: {err}"); + assert!( + err.contains("come back"), + "reassures they survive a restart: {err}" + ); assert!(!err.contains("REQ-"), "no internal tag leaks: {err}"); } @@ -37921,7 +39509,10 @@ mod tests { msg.contains("No flag overrides this"), "says no flag helps: {msg}" ); - assert!(msg.contains("--force"), "names the flag that does NOT work: {msg}"); + assert!( + msg.contains("--force"), + "names the flag that does NOT work: {msg}" + ); } // No ground = a human. The endpoint deny must not fire at all, so the @@ -37950,10 +39541,19 @@ mod tests { &residents, ) .expect("env ground refuses"); - assert!(env.contains("doyle") && env.contains("perri"), "names residents: {env}"); + assert!( + env.contains("doyle") && env.contains("perri"), + "names residents: {env}" + ); assert!(env.contains('2'), "counts the blast radius: {env}"); - assert!(env.contains("$SPT_ENDPOINT_ID is set"), "names the ground: {env}"); - assert!(env.contains("unset SPT_ENDPOINT_ID"), "cure fits the ground: {env}"); + assert!( + env.contains("$SPT_ENDPOINT_ID is set"), + "names the ground: {env}" + ); + assert!( + env.contains("unset SPT_ENDPOINT_ID"), + "cure fits the ground: {env}" + ); // ESCAPE-HATCH PIN: env scrubbed ⇒ ancestry ground ⇒ still refused, and // the cure must NOT be "unset something" — unsetting cleared nothing. @@ -37962,7 +39562,10 @@ mod tests { &residents, ) .expect("an ancestry ground still refuses after the env markers are cleared"); - assert!(anc.contains("doyle") && anc.contains("perri"), "names residents: {anc}"); + assert!( + anc.contains("doyle") && anc.contains("perri"), + "names residents: {anc}" + ); assert!( anc.contains("hosted session 'todlando'"), "names the ground: {anc}" @@ -37978,12 +39581,13 @@ mod tests { // A refusal with nothing hosted still explains what it protects, rather // than printing an empty list. - let none = broker_stop_endpoint_denial( - Some(&AgentGround::EnvMarker("OWL_SESSION_ID")), - &[], - ) - .expect("still refuses with no residents"); - assert!(none.contains("every spt-hosted endpoint"), "explains itself: {none}"); + let none = + broker_stop_endpoint_denial(Some(&AgentGround::EnvMarker("OWL_SESSION_ID")), &[]) + .expect("still refuses with no residents"); + assert!( + none.contains("every spt-hosted endpoint"), + "explains itself: {none}" + ); for msg in [env, anc, none] { assert!(!msg.contains("REQ-"), "no internal tag leaks: {msg}"); @@ -38015,7 +39619,10 @@ mod tests { let netless = render_connection_lines(false, Some(0), 1_000_000, 30_000); assert!(netless.contains("no connection"), "surfaces the real cause"); assert!(netless.contains("waiting on network")); - assert!(!netless.contains("STALLED"), "no false stall off a stale heartbeat"); + assert!( + !netless.contains("STALLED"), + "no false stall off a stale heartbeat" + ); // Net up, fresh heartbeat ⇒ live. let live = render_connection_lines(true, Some(95_000), 100_000, 30_000); assert!(live.contains("peer pump: live")); @@ -38117,7 +39724,11 @@ mod tests { true }); let elapsed = start.elapsed(); - assert_eq!(got, vec![true, false, true], "wedged probe reads false, fast ones true, order kept"); + assert_eq!( + got, + vec![true, false, true], + "wedged probe reads false, fast ones true, order kept" + ); assert!( elapsed < 4 * ceiling, "the wedged probe costs one ceiling, not its full 1500ms sleep; got {elapsed:?}" @@ -38253,10 +39864,7 @@ mod tests { assert!(subnet.contains("spt subnet create")); assert!(subnet.contains("spt subnet show-code")); assert!(subnet.contains("spt subnet join")); - assert!( - subnet.contains("6-digit"), - "the pairing code is documented" - ); + assert!(subnet.contains("6-digit"), "the pairing code is documented"); assert!( subnet.contains("@"), "reaching a remote agent by node-qualified id is documented" @@ -38338,14 +39946,22 @@ mod tests { premodes.create_subnet("old", Mode::Closed).expect("mint"); premodes.subnets[0].mode = None; let mut pre_access = AccessStore::default(); - assert!(!capture_minted_mode(&mut pre_access, &premodes, Some("old"))); + assert!(!capture_minted_mode( + &mut pre_access, + &premodes, + Some("old") + )); assert!(pre_access.captured_subnets.is_empty()); // FIDELITY: the DECLARED mode is what lands, not a constant. let mut open_store = SubnetStore::default(); open_store.create_subnet("free", Mode::Open).expect("mint"); let mut open_access = AccessStore::default(); - assert!(capture_minted_mode(&mut open_access, &open_store, Some("free"))); + assert!(capture_minted_mode( + &mut open_access, + &open_store, + Some("free") + )); assert_eq!( open_access.captured_subnet_mode("free"), Some(Mode::Open), @@ -38359,7 +39975,8 @@ mod tests { // ceremony never declared. #[test] fn the_mint_probe_answers_only_for_a_fresh_mint() { - const SEED: [u8; spt_store::subnet::TOTP_SEED_LEN] = [7u8; spt_store::subnet::TOTP_SEED_LEN]; + const SEED: [u8; spt_store::subnet::TOTP_SEED_LEN] = + [7u8; spt_store::subnet::TOTP_SEED_LEN]; let minted = Resolved::Subnet { name: "work".into(), seed: SEED, @@ -38373,7 +39990,11 @@ mod tests { minted: false, admin_seed: None, }; - assert_eq!(minted_name(&shown), None, "a show-code of a stored subnet is not a mint"); + assert_eq!( + minted_name(&shown), + None, + "a show-code of a stored subnet is not a mint" + ); // Labelled rather than `{:?}`-printed: `Resolved` carries seed bytes and // deliberately has no Debug — the redaction posture of the record it comes // from. A test is not a reason to open that door. @@ -38381,7 +40002,10 @@ mod tests { ("exists", Resolved::Exists("work".into())), ("not-found", Resolved::NotFound("work".into())), ("corrupt", Resolved::Corrupt("work".into())), - ("ambiguous", Resolved::Ambiguous(vec!["a".into(), "b".into()])), + ( + "ambiguous", + Resolved::Ambiguous(vec!["a".into(), "b".into()]), + ), ("empty", Resolved::Empty), ] { assert_eq!(minted_name(&other), None, "{label} is not a mint"); @@ -38450,8 +40074,14 @@ mod tests { }, ]; let view = render_subnet_status(&rows, true, false); - assert!(view.contains("MODE"), "the bare table has a mode column: {view}"); - assert!(view.contains("CAPTURED HERE"), "and a captured-here column: {view}"); + assert!( + view.contains("MODE"), + "the bare table has a mode column: {view}" + ); + assert!( + view.contains("CAPTURED HERE"), + "and a captured-here column: {view}" + ); assert!( view.contains("closed"), "the declared mode of the closed subnet is stated: {view}" @@ -38503,7 +40133,8 @@ mod tests { fn store_with(names: &[&str]) -> SubnetStore { let mut s = SubnetStore::default(); for n in names { - s.create_subnet(n, spt_store::access::Mode::Open).expect("create"); + s.create_subnet(n, spt_store::access::Mode::Open) + .expect("create"); } s } @@ -38557,7 +40188,11 @@ mod tests { fn create_new_mints_shows_and_requests_save() { let mut store = SubnetStore::default(); let r = decide_show_code( - resolve(&mut store, None, Some(("fresh".into(), spt_store::access::Mode::Open))), + resolve( + &mut store, + None, + Some(("fresh".into(), spt_store::access::Mode::Open)), + ), 42, Elevation::Elevated, ); @@ -38575,7 +40210,11 @@ mod tests { fn create_new_existing_name_is_usage_error() { let mut store = store_with(&["home"]); let r = decide_show_code( - resolve(&mut store, None, Some(("home".into(), spt_store::access::Mode::Open))), + resolve( + &mut store, + None, + Some(("home".into(), spt_store::access::Mode::Open)), + ), 0, Elevation::Elevated, ); @@ -38612,7 +40251,11 @@ mod tests { fn not_elevated_refuses_without_leaking_code_or_saving() { let mut store = SubnetStore::default(); let r = decide_show_code( - resolve(&mut store, None, Some(("fresh".into(), spt_store::access::Mode::Open))), + resolve( + &mut store, + None, + Some(("fresh".into(), spt_store::access::Mode::Open)), + ), 0, Elevation::NotElevated, ); @@ -38775,7 +40418,10 @@ mod tests { extract_release_archive(&archive, &dest).expect("fat archive extracts for this platform"); // Shared root placed. - assert!(dest.join("manifest.toml").is_file(), "shared manifest.toml placed"); + assert!( + dest.join("manifest.toml").is_file(), + "shared manifest.toml placed" + ); assert!( dest.join("strings").join("en.toml").is_file(), "shared strings/ placed" @@ -38866,7 +40512,10 @@ mod tests { std::fs::create_dir_all(&dest).unwrap(); extract_release_archive(&archive, &dest).expect("legacy flat archive extracts"); - assert!(dest.join("manifest.toml").is_file(), "flat manifest.toml placed"); + assert!( + dest.join("manifest.toml").is_file(), + "flat manifest.toml placed" + ); assert!( dest.join("strings").join("en.toml").is_file(), "flat strings/ placed" @@ -38965,7 +40614,8 @@ mod tests { // 5. Idempotent: re-applying the SAME staged archive is a no-op (every file // already matches, so nothing is swapped) and still succeeds. - apply_release_crc_swap(&staged, &dest).expect("re-applying an identical release is a no-op"); + apply_release_crc_swap(&staged, &dest) + .expect("re-applying an identical release is a no-op"); assert_eq!( std::fs::read(dest.join("manifest.toml")).unwrap(), b"version = 2\n", diff --git a/crates/spt/src/elevation.rs b/crates/spt/src/elevation.rs index 9d25cd1f..e2a1eb0f 100644 --- a/crates/spt/src/elevation.rs +++ b/crates/spt/src/elevation.rs @@ -135,7 +135,8 @@ pub enum ElevatePath { /// Candidate terminal emulators, in preference order, for the `DISPLAY ∧ no-pkexec` /// Linux-desktop arm (`x-terminal-emulator` is the Debian alternatives symlink). -pub const TERMINAL_EMULATORS: &[&str] = &["x-terminal-emulator", "gnome-terminal", "konsole", "xterm"]; +pub const TERMINAL_EMULATORS: &[&str] = + &["x-terminal-emulator", "gnome-terminal", "konsole", "xterm"]; /// The pure elevation-path decision (the testable seam — the cross-platform /// generalization of the old Unix-only auto-sudo check). Loop-safety is enforced @@ -228,8 +229,7 @@ pub fn terminal_argv(term: &str, exe: &str, args: &[String]) -> Vec { // no-injection unit test; dead in the non-Windows BIN target only. #[cfg_attr(not(windows), allow(dead_code))] fn windows_quote_arg(arg: &str) -> String { - let needs_quotes = - arg.is_empty() || arg.chars().any(|c| c == ' ' || c == '\t' || c == '"'); + let needs_quotes = arg.is_empty() || arg.chars().any(|c| c == ' ' || c == '\t' || c == '"'); if !needs_quotes { return arg.to_string(); } @@ -445,16 +445,34 @@ mod tests { fn unix_path_order_tty_then_pkexec_then_terminal_then_hint() { let n = Elevation::NotElevated; // Interactive TTY wins regardless of desktop state. - assert_eq!(decide_elevation_path(Os::Unix, n, true, true, true, true), ElevatePath::InlineSudo); - assert_eq!(decide_elevation_path(Os::Unix, n, true, false, false, false), ElevatePath::InlineSudo); + assert_eq!( + decide_elevation_path(Os::Unix, n, true, true, true, true), + ElevatePath::InlineSudo + ); + assert_eq!( + decide_elevation_path(Os::Unix, n, true, false, false, false), + ElevatePath::InlineSudo + ); // No TTY, desktop + pkexec → pkexec (preferred over a terminal emulator). - assert_eq!(decide_elevation_path(Os::Unix, n, false, true, true, true), ElevatePath::Pkexec); + assert_eq!( + decide_elevation_path(Os::Unix, n, false, true, true, true), + ElevatePath::Pkexec + ); // No TTY, desktop, no pkexec, has terminal → terminal emulator. - assert_eq!(decide_elevation_path(Os::Unix, n, false, true, false, true), ElevatePath::TerminalEmulator); + assert_eq!( + decide_elevation_path(Os::Unix, n, false, true, false, true), + ElevatePath::TerminalEmulator + ); // Desktop present but neither pkexec nor a terminal → print floor. - assert_eq!(decide_elevation_path(Os::Unix, n, false, true, false, false), ElevatePath::PrintHint); + assert_eq!( + decide_elevation_path(Os::Unix, n, false, true, false, false), + ElevatePath::PrintHint + ); // No TTY, no DISPLAY (headless) → print floor even with pkexec/term present. - assert_eq!(decide_elevation_path(Os::Unix, n, false, false, true, true), ElevatePath::PrintHint); + assert_eq!( + decide_elevation_path(Os::Unix, n, false, false, true, true), + ElevatePath::PrintHint + ); } // [unit->REQ-ELEVATE-1] Windows: interactive → UAC console; headless/redirected @@ -462,9 +480,18 @@ mod tests { #[test] fn windows_uac_only_interactive_other_always_prints() { let n = Elevation::NotElevated; - assert_eq!(decide_elevation_path(Os::Windows, n, true, false, false, false), ElevatePath::UacWindow); - assert_eq!(decide_elevation_path(Os::Windows, n, false, false, false, false), ElevatePath::PrintHint); - assert_eq!(decide_elevation_path(Os::Other, n, true, true, true, true), ElevatePath::PrintHint); + assert_eq!( + decide_elevation_path(Os::Windows, n, true, false, false, false), + ElevatePath::UacWindow + ); + assert_eq!( + decide_elevation_path(Os::Windows, n, false, false, false, false), + ElevatePath::PrintHint + ); + assert_eq!( + decide_elevation_path(Os::Other, n, true, true, true, true), + ElevatePath::PrintHint + ); } // [unit->REQ-HAZARD-SELF-ELEVATE] [unit->REQ-HAZARD-SUDO-SECURE-PATH] every @@ -485,14 +512,26 @@ mod tests { let term = terminal_argv("x-terminal-emulator", exe, &a); assert_eq!( term, - vec!["x-terminal-emulator", "-e", "sudo", exe, "subnet", "create", "home fleet"] + vec![ + "x-terminal-emulator", + "-e", + "sudo", + exe, + "subnet", + "create", + "home fleet" + ] ); // Verbatim: the args tail is identical (no added/altered flags), absolute exe. for argv in [&sudo, &pk] { let exe_pos = argv.iter().position(|s| s == exe).expect("abs exe present"); assert!(exe.starts_with('/'), "absolute exe path"); - assert_eq!(&argv[exe_pos + 1..], a.as_slice(), "verbatim args, no widening"); + assert_eq!( + &argv[exe_pos + 1..], + a.as_slice(), + "verbatim args, no widening" + ); } } @@ -508,9 +547,20 @@ mod tests { let a = vec!["subnet".to_string(), "create".to_string(), evil.clone()]; // argv-array launchers: the malicious string is exactly one trailing element. - for argv in [sudo_argv(exe, &a), pkexec_argv(exe, &a), terminal_argv("xterm", exe, &a)] { - assert_eq!(argv.last().unwrap(), &evil, "crafted arg stays one argv element"); - assert!(!argv.iter().any(|s| s == "sh" || s == "-c"), "no sh -c wrapper"); + for argv in [ + sudo_argv(exe, &a), + pkexec_argv(exe, &a), + terminal_argv("xterm", exe, &a), + ] { + assert_eq!( + argv.last().unwrap(), + &evil, + "crafted arg stays one argv element" + ); + assert!( + !argv.iter().any(|s| s == "sh" || s == "-c"), + "no sh -c wrapper" + ); } // Windows params: each arg individually quoted; a quote-bearing arg is escaped @@ -520,7 +570,10 @@ mod tests { let inject = windows_runas_params(&[r#"a" & calc.exe"#.to_string()]); // The interior quote is backslash-escaped so it cannot terminate the arg early. assert!(inject.contains(r#"\""#), "interior quote escaped: {inject}"); - assert!(!inject.to_lowercase().contains("cmd /c"), "no cmd /c wrapper"); + assert!( + !inject.to_lowercase().contains("cmd /c"), + "no cmd /c wrapper" + ); } // [unit->REQ-HAZARD-SELF-ELEVATE] [unit->REQ-HAZARD-SUDO-SECURE-PATH] the print-hint @@ -536,10 +589,17 @@ mod tests { assert!(unix.starts_with("sudo /"), "absolute path under sudo"); // Spaced arg: shell-quoted in the printed sudo line (KNOWN-HAZARDS 5.10). - let spaced = print_hint_command(Os::Unix, "/usr/local/bin/spt", &args(&["subnet", "create", "home fleet"])); + let spaced = print_hint_command( + Os::Unix, + "/usr/local/bin/spt", + &args(&["subnet", "create", "home fleet"]), + ); assert_eq!(spaced, "sudo /usr/local/bin/spt subnet create 'home fleet'"); let win = print_hint_command(Os::Windows, "C:\\Users\\me\\spt.exe", &a); - assert!(win.contains("C:\\Users\\me\\spt.exe"), "absolute exe in hint: {win}"); + assert!( + win.contains("C:\\Users\\me\\spt.exe"), + "absolute exe in hint: {win}" + ); } } diff --git a/crates/spt/src/helpfmt.rs b/crates/spt/src/helpfmt.rs index d62a721f..8e67760d 100644 --- a/crates/spt/src/helpfmt.rs +++ b/crates/spt/src/helpfmt.rs @@ -62,8 +62,8 @@ pub fn stderr_color() -> bool { fn resolve_console_color(want: bool, console_vt: Option) -> bool { match (want, console_vt) { (false, _) => false, - (true, None) => true, // not a console → piped/forced bytes pass through - (true, Some(ok)) => ok, // a console → color only if VT could be enabled + (true, None) => true, // not a console → piped/forced bytes pass through + (true, Some(ok)) => ok, // a console → color only if VT could be enabled } } @@ -367,10 +367,7 @@ mod tests { #[test] fn nested_code_inside_bold_styles_both() { // `**`code`**` → bold around a cyan code span. - assert_eq!( - render("**`x`**", true), - "\x1b[1m\x1b[36mx\x1b[39m\x1b[22m" - ); + assert_eq!(render("**`x`**", true), "\x1b[1m\x1b[36mx\x1b[39m\x1b[22m"); assert_eq!(render("**`x`**", false), "x"); } @@ -429,7 +426,10 @@ mod tests { fn preexisting_ansi_is_passed_through_untouched() { let styled = "\x1b[31mred **still bold**\x1b[0m"; // The CSI prefix is copied verbatim; the inner `**bold**` still renders. - assert_eq!(render(styled, true), "\x1b[31mred \x1b[1mstill bold\x1b[22m\x1b[0m"); + assert_eq!( + render(styled, true), + "\x1b[31mred \x1b[1mstill bold\x1b[22m\x1b[0m" + ); assert_eq!(render(styled, false), "\x1b[31mred still bold\x1b[0m"); } diff --git a/crates/spt/src/main.rs b/crates/spt/src/main.rs index 81268a6a..643bfa43 100644 --- a/crates/spt/src/main.rs +++ b/crates/spt/src/main.rs @@ -227,8 +227,13 @@ mod tests { "failed printing to stdout: No space left on device (os error 28)" )); // NOT a stdio-print panic at all → untouched. - assert!(!is_broken_pipe_panic("index out of bounds: the len is 0 but the index is 3")); - assert!(!is_broken_pipe_panic("Broken pipe (os error 32)"), "must also be a print panic"); + assert!(!is_broken_pipe_panic( + "index out of bounds: the len is 0 but the index is 3" + )); + assert!( + !is_broken_pipe_panic("Broken pipe (os error 32)"), + "must also be a print panic" + ); } // [unit->REQ-CLI-STACK-HEADROOM] The wrapper's whole risk is fidelity: moving diff --git a/crates/spt/src/picker/data.rs b/crates/spt/src/picker/data.rs index bdd7e644..e916b8d4 100644 --- a/crates/spt/src/picker/data.rs +++ b/crates/spt/src/picker/data.rs @@ -125,7 +125,8 @@ fn node_label_map() -> std::collections::BTreeMap { for s in &subnets.subnets { if let Some(reg) = regs.get(&s.name) { for (node, label) in reg.node_labels() { - map.entry(node.to_string()).or_insert_with(|| label.to_string()); + map.entry(node.to_string()) + .or_insert_with(|| label.to_string()); } } } @@ -162,7 +163,12 @@ fn reconcile_self_owned(rows: &mut [EndpointRow]) { let local: HashMap, String)> = rows .iter() .filter(|r| r.is_local) - .map(|r| (r.id.clone(), (r.status, r.controllable, r.endpoint_type.clone()))) + .map(|r| { + ( + r.id.clone(), + (r.status, r.controllable, r.endpoint_type.clone()), + ) + }) .collect(); for row in rows.iter_mut() { if row.is_local { @@ -425,10 +431,7 @@ fn path_under(path: &Path, base: &Path) -> bool { /// - an absent row / absent index → empty (renders `-`). // [impl->REQ-PROJECT-INDEX-READER-CUTOVER] // [impl->REQ-PICKER-PROJECT-HISTORY-TRUTH] -pub fn indexed_project_refs( - read: &spt_store::projindex::IndexRead, - id: &str, -) -> Vec { +pub fn indexed_project_refs(read: &spt_store::projindex::IndexRead, id: &str) -> Vec { let Some(row) = read.project_for(id) else { return Vec::new(); }; @@ -475,10 +478,7 @@ pub fn indexed_latest_project_ref( /// reader git work): an unindexed cwd (stale index / brand-new dir) degrades /// to the dir's folder name — a pure path read, human-recognizable, no git. // [impl->REQ-PROJECT-INDEX-READER-CUTOVER] -fn resume_rows_for( - read: &spt_store::projindex::IndexRead, - perch_path: &Path, -) -> Vec { +fn resume_rows_for(read: &spt_store::projindex::IndexRead, perch_path: &Path) -> Vec { let lookup = |dir: &Path| -> (String, String) { if let spt_store::projindex::IndexRead::Snapshot(idx) = read { if let Some(c) = idx.project_for_cwd(dir) { @@ -523,7 +523,10 @@ fn resume_rows_from( // unresumable row. A pre-migration row with no cwd is kept (its title // falls back to the boundary trigger). // [impl->REQ-SESSIONS-LOG-ENDPOINT-ATTRIBUTION] - if e.cwd.as_deref().is_some_and(|cwd| path_under(Path::new(cwd), internal_root)) { + if e.cwd + .as_deref() + .is_some_and(|cwd| path_under(Path::new(cwd), internal_root)) + { return None; } // The row title shows the DISPLAY name (A1) of the session's own project. @@ -573,14 +576,22 @@ mod tests { ) -> Vec { spt_store::projderive::project_refs_from(entries, origin_cwd, store_ids, owlery, derive) .into_iter() - .map(|d| ProjectRef { id: d.id, dir: d.dir, display: d.display }) + .map(|d| ProjectRef { + id: d.id, + dir: d.dir, + display: d.display, + }) .collect() } fn row(id: &str, is_local: bool, status: EpStatus) -> EndpointRow { EndpointRow { id: id.to_string(), - group: if is_local { "local".into() } else { "sub:n".into() }, + group: if is_local { + "local".into() + } else { + "sub:n".into() + }, node: if is_local { "LOCAL".into() } else { "n".into() }, node_key: if is_local { String::new() } else { "n".into() }, status, @@ -613,14 +624,26 @@ mod tests { use crate::picker::model::EpDisplay; // The derivation rule, directly: unbound (alive=false) IS online; a true // dead perch (neither) is offline. - assert_eq!(row_status(false, true), EpStatus::Online, "live unbound → online"); + assert_eq!( + row_status(false, true), + EpStatus::Online, + "live unbound → online" + ); assert_eq!(row_status(true, false), EpStatus::Online, "alive → online"); assert_eq!(row_status(true, true), EpStatus::Online); - assert_eq!(row_status(false, false), EpStatus::Offline, "neither → offline"); + assert_eq!( + row_status(false, false), + EpStatus::Offline, + "neither → offline" + ); // The full seam: feed the real-rule status + the roster unbound flag into an // EndpointRow exactly as local_rows does → display_status == hollow Unbound. - let mut r = row("skeleton", true, row_status(/*alive*/ false, /*unbound*/ true)); + let mut r = row( + "skeleton", + true, + row_status(/*alive*/ false, /*unbound*/ true), + ); r.is_unbound = true; // local_rows sets is_unbound = p.unbound r.controllable = Some(false); // would be amber HarnessOnly if not unbound assert_eq!( @@ -629,7 +652,11 @@ mod tests { "live unbound derives Online → display resolves to hollow Unbound (not gray Offline)" ); // And it must NOT have read as offline (the bug) — no resume rows path etc. - assert_ne!(r.display_status(), EpDisplay::Offline, "never gray-offline for a live unbound"); + assert_ne!( + r.display_status(), + EpDisplay::Offline, + "never gray-offline for a live unbound" + ); } // [int->REQ-ENDPOINT-UNBOUND-ATTACH] the REAL render seam (the one no unit @@ -739,7 +766,10 @@ mod tests { spt_store::info::write_info(&p, &rec).unwrap(); } let ids: Vec = gather_endpoints().into_iter().map(|r| r.id).collect(); - assert!(ids.contains(&"realagent".to_string()), "the drivable agent is offered"); + assert!( + ids.contains(&"realagent".to_string()), + "the drivable agent is offered" + ); assert!( !ids.contains(&"cc-random-9f3a".to_string()), "a worker is never a run-picker row (REQ-WORKER-PICKER-EXCLUDED)" @@ -769,7 +799,9 @@ mod tests { // The subnet must exist locally for subnet_rows to project its snapshot. let mut subnets = spt_store::subnet::SubnetStore::load(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let remote_node = "remote00node00hex"; @@ -822,7 +854,11 @@ mod tests { "a cold (Suspended) remote perch reads Suspended — NOT online (W4), \ and distinct from Offline (W5)" ); - assert_ne!(dead.status, EpStatus::Online, "the core W4 guarantee: never false-green"); + assert_ne!( + dead.status, + EpStatus::Online, + "the core W4 guarantee: never false-green" + ); assert_eq!( dead.display_status(), crate::picker::model::EpDisplay::Suspended, @@ -851,7 +887,9 @@ mod tests { let _home = crate::testutil::isolated_home(); let mut subnets = spt_store::subnet::SubnetStore::load(); - subnets.create_subnet("home", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("home", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let remote_node = "remote00node00hex"; @@ -860,23 +898,24 @@ mod tests { // controlled remote endpoint gossips `controlled=true` with // `controller_node=None` (the by=None dispatch_spawn case), and must still // render blue cross-node. - let inst = |bound: bool, controller: Option<&str>, harness: bool, controlled: bool| Instance { - node: remote_node.to_string(), - status: Status::Active, - epoch: 5, - resources: None, - last_active_ms: None, - shell_adapters: Vec::new(), - node_label: Some("REMOTE".to_string()), - machine_id: None, - endpoint_type: None, - bound, - controller_node: controller.map(str::to_string), - harness_only: harness, - adapter: None, - recent_projects: Vec::new(), - controlled, - }; + let inst = + |bound: bool, controller: Option<&str>, harness: bool, controlled: bool| Instance { + node: remote_node.to_string(), + status: Status::Active, + epoch: 5, + resources: None, + last_active_ms: None, + shell_adapters: Vec::new(), + node_label: Some("REMOTE".to_string()), + machine_id: None, + endpoint_type: None, + bound, + controller_node: controller.map(str::to_string), + harness_only: harness, + adapter: None, + recent_projects: Vec::new(), + controlled, + }; let mut reg = SubnetRegistry::new(); // bound + free + not harness → green Online. reg.merge_instance("freeep", inst(true, None, false, false)); @@ -900,7 +939,11 @@ mod tests { let snap_dir = perch::identity_dir().join("registry"); std::fs::create_dir_all(&snap_dir).unwrap(); - std::fs::write(snap_dir.join("home.json"), serde_json::to_string(®).unwrap()).unwrap(); + std::fs::write( + snap_dir.join("home.json"), + serde_json::to_string(®).unwrap(), + ) + .unwrap(); let rows = gather_endpoints(); let disp = |id: &str| { @@ -909,28 +952,60 @@ mod tests { .unwrap_or_else(|| panic!("remote row {id} missing")) .display_status() }; - assert_eq!(disp("freeep"), EpDisplay::Online, "remote bound+free → green Online"); - assert_eq!(disp("unbep"), EpDisplay::Unbound, "remote unbound → red Unbound (parity)"); - assert_eq!(disp("ctlep"), EpDisplay::Controlled, "remote-driven → blue (parity)"); + assert_eq!( + disp("freeep"), + EpDisplay::Online, + "remote bound+free → green Online" + ); + assert_eq!( + disp("unbep"), + EpDisplay::Unbound, + "remote unbound → red Unbound (parity)" + ); + assert_eq!( + disp("ctlep"), + EpDisplay::Controlled, + "remote-driven → blue (parity)" + ); assert_eq!( disp("locctlep"), EpDisplay::Controlled, "locally-controlled remote (controlled=true, no gossiped driver) → blue (#4 decouple)" ); - assert_eq!(disp("harnep"), EpDisplay::HarnessOnly, "remote harness-only → amber (parity)"); + assert_eq!( + disp("harnep"), + EpDisplay::HarnessOnly, + "remote harness-only → amber (parity)" + ); // The REMOTE-driven row renders its driver as the canonical node display (a // name/keyprefix), not raw hex — the desc-pane `controlled by ` pin. let ctl = rows.iter().find(|r| r.id == "ctlep").unwrap(); - assert!(ctl.driven_by.is_some(), "a remote-driven row carries its driver for the pin"); + assert!( + ctl.driven_by.is_some(), + "a remote-driven row carries its driver for the pin" + ); // The LOCALLY-controlled row is blue WITHOUT a driver pin — the any-controller // truth came from `controlled`, not the (absent) WHO datum. let loc = rows.iter().find(|r| r.id == "locctlep").unwrap(); - assert!(loc.controlled, "locally-controlled remote reads controlled from gossip"); - assert!(loc.driven_by.is_none(), "no gossiped driver → no pin, still blue"); + assert!( + loc.controlled, + "locally-controlled remote reads controlled from gossip" + ); + assert!( + loc.driven_by.is_none(), + "no gossiped driver → no pin, still blue" + ); // #4 end-to-end: the gathered row surfaces the REAL gossiped adapter + project // history (not the blurb, not a hardcoded empty) through the whole pipeline. - assert_eq!(loc.adapter_profile, "claude-spt:doyle", "gossiped adapter surfaced by gather"); - assert_eq!(loc.project_history, vec!["spt-core", "owl"], "gossiped projects surfaced by gather"); + assert_eq!( + loc.adapter_profile, "claude-spt:doyle", + "gossiped adapter surfaced by gather" + ); + assert_eq!( + loc.project_history, + vec!["spt-core", "owl"], + "gossiped projects surfaced by gather" + ); } // [int->REQ-PICKER-NODE-GROUPING] bug #13: a machine shared across TWO subnets @@ -945,8 +1020,12 @@ mod tests { let _home = crate::testutil::isolated_home(); let mut subnets = spt_store::subnet::SubnetStore::load(); - subnets.create_subnet("bignet", spt_store::access::Mode::Open).unwrap(); - subnets.create_subnet("sptdev", spt_store::access::Mode::Open).unwrap(); + subnets + .create_subnet("bignet", spt_store::access::Mode::Open) + .unwrap(); + subnets + .create_subnet("sptdev", spt_store::access::Mode::Open) + .unwrap(); subnets.save().unwrap(); let remote_node = "remote00node00hex"; @@ -977,27 +1056,54 @@ mod tests { let snap_dir = perch::identity_dir().join("registry"); std::fs::create_dir_all(&snap_dir).unwrap(); - std::fs::write(snap_dir.join("bignet.json"), serde_json::to_string(®_big).unwrap()) - .unwrap(); - std::fs::write(snap_dir.join("sptdev.json"), serde_json::to_string(®_dev).unwrap()) - .unwrap(); + std::fs::write( + snap_dir.join("bignet.json"), + serde_json::to_string(®_big).unwrap(), + ) + .unwrap(); + std::fs::write( + snap_dir.join("sptdev.json"), + serde_json::to_string(®_dev).unwrap(), + ) + .unwrap(); let rows = gather_endpoints(); let eel: Vec<&EndpointRow> = rows.iter().filter(|r| r.id == "eel-a").collect(); - assert_eq!(eel.len(), 1, "the shared machine's endpoint is ONE row, not one per subnet"); + assert_eq!( + eel.len(), + 1, + "the shared machine's endpoint is ONE row, not one per subnet" + ); let r = eel[0]; // Grouped by the MACHINE (node display), not "{subnet}:{node}". - assert!(!r.group.contains(':'), "group is the machine, not subnet:node: {}", r.group); - assert!(r.group.contains("REMOTE"), "group is the machine display: {}", r.group); + assert!( + !r.group.contains(':'), + "group is the machine, not subnet:node: {}", + r.group + ); + assert!( + r.group.contains("REMOTE"), + "group is the machine display: {}", + r.group + ); // Both shared subnets are unioned onto the single row (order = gather order). assert!( r.subnets.contains(&"bignet".to_string()) && r.subnets.contains(&"sptdev".to_string()), "both shared subnets listed beneath the machine: {:?}", r.subnets ); - assert_eq!(r.subnets.len(), 2, "no duplicate subnet entries: {:?}", r.subnets); + assert_eq!( + r.subnets.len(), + 2, + "no duplicate subnet entries: {:?}", + r.subnets + ); // Most-alive reconcile: the warm (Dormant→Online) sighting wins over the cold. - assert_eq!(r.status, EpStatus::Online, "most-alive status wins across subnets"); + assert_eq!( + r.status, + EpStatus::Online, + "most-alive status wins across subnets" + ); } // [unit->REQ-PICKER-3] a self-owned endpoint dual-listed in Local + Subnet, @@ -1046,7 +1152,10 @@ mod tests { // folder name lowercased (the repo-less fallback). Keeps the derivation unit pure // + fast; id==display here since a folder-name fallback has no distinct URL tail. fn folder_derive(p: &Path) -> (String, String) { - let name = p.file_name().map(|n| n.to_string_lossy().to_lowercase()).unwrap_or_default(); + let name = p + .file_name() + .map(|n| n.to_string_lossy().to_lowercase()) + .unwrap_or_default(); (name.clone(), name) } @@ -1069,13 +1178,18 @@ mod tests { sess("C:/Users/x/spt-core/owlery/hall-a/nested/hall-a-psyche"), ]; let rows = resume_rows_from(entries, owlery, folder_derive); - assert_eq!(rows.len(), 2, "the owlery-internal psyche session is filtered out"); + assert_eq!( + rows.len(), + 2, + "the owlery-internal psyche session is filtered out" + ); // Newest-first; each row carries its OWN project, not a shared head. assert_eq!(rows[0].project, "beta"); assert_eq!(rows[1].project, "alpha"); // No surviving row points into the owlery. assert!( - rows.iter().all(|r| !r.cwd.as_deref().unwrap_or_default().contains("/owlery/")), + rows.iter() + .all(|r| !r.cwd.as_deref().unwrap_or_default().contains("/owlery/")), "no resume row may reference an owlery-internal session" ); } @@ -1147,7 +1261,10 @@ mod tests { let mut m = std::collections::BTreeMap::new(); m.insert( "c:/p/newest".to_string(), - CwdProject { id: "newest".into(), display: "Newest".into() }, + CwdProject { + id: "newest".into(), + display: "Newest".into(), + }, ); m }, @@ -1157,7 +1274,10 @@ mod tests { let refs = indexed_project_refs(&read, "full"); assert_eq!(refs.len(), 2); assert_eq!(refs[0].id, "newest"); - assert_eq!(refs[0].dir, "C:/p/newest", "dirs survive for #5 launch-into"); + assert_eq!( + refs[0].dir, "C:/p/newest", + "dirs survive for #5 launch-into" + ); assert_eq!(refs[1].id, "older"); assert_eq!( indexed_latest_project_ref(&read, "full").map(|r| r.id), @@ -1217,19 +1337,28 @@ mod tests { let mut idx = ProjectIndex::empty(1); idx.cwds.insert( "c:/p/indexed-proj".to_string(), - CwdProject { id: "the-slug".into(), display: "TheRealDisplay".into() }, + CwdProject { + id: "the-slug".into(), + display: "TheRealDisplay".into(), + }, ); let rows = resume_rows_for(&IndexRead::Snapshot(idx), &perch_path); assert_eq!(rows.len(), 2); // Newest-first: the unseen dir (appended last) leads with its folder name… - assert_eq!(rows[0].project, "unseen-dir", "unindexed cwd → folder-name fallback"); + assert_eq!( + rows[0].project, "unseen-dir", + "unindexed cwd → folder-name fallback" + ); // …and the indexed cwd renders the MATERIALIZED display (case + tail // exactly as the writer derived it — never re-derived here). assert_eq!(rows[1].project, "TheRealDisplay"); // Degraded (Absent) index: every row still titles fast via the fallback. let rows = resume_rows_for(&IndexRead::Absent(AbsentReason::Missing), &perch_path); - assert_eq!(rows[1].project, "Indexed-Proj", "absent index → folder name, no stall"); + assert_eq!( + rows[1].project, "Indexed-Proj", + "absent index → folder name, no stall" + ); assert_eq!( spt_store::gitrun::git_spawn_count(), @@ -1246,9 +1375,7 @@ mod tests { // would have cost 2 perches × branch walks before the cutover. #[test] fn gather_endpoints_projects_from_seeded_index_with_zero_git() { - use spt_store::projindex::{ - CwdProject, EndpointProject, ProjectIndex, ProjectRefEntry, - }; + use spt_store::projindex::{CwdProject, EndpointProject, ProjectIndex, ProjectRefEntry}; let _home = crate::testutil::isolated_home(); // Two offline local perches; ep-idx has a resume-able ledger row. @@ -1292,7 +1419,10 @@ mod tests { ); idx.cwds.insert( "c:/p/proj-x".to_string(), - CwdProject { id: "proj-x".into(), display: "proj-x".into() }, + CwdProject { + id: "proj-x".into(), + display: "proj-x".into(), + }, ); spt_store::projindex::write_index(&idx).unwrap(); @@ -1307,14 +1437,23 @@ mod tests { let ep = rows.iter().find(|r| r.id == "ep-idx").expect("ep-idx row"); assert_eq!(ep.project_history, vec!["proj-x".to_string()]); assert_eq!(ep.project_refs.len(), 1); - assert_eq!(ep.project_refs[0].dir, "C:/p/proj-x", "launch-into dir carried"); + assert_eq!( + ep.project_refs[0].dir, "C:/p/proj-x", + "launch-into dir carried" + ); assert_eq!( ep.resume_rows.first().map(|r| r.project.as_str()), Some("proj-x"), "resume title reads the index cwd map" ); - let bare = rows.iter().find(|r| r.id == "ep-bare").expect("ep-bare row"); - assert!(bare.project_history.is_empty(), "unindexed endpoint renders '-'"); + let bare = rows + .iter() + .find(|r| r.id == "ep-bare") + .expect("ep-bare row"); + assert!( + bare.project_history.is_empty(), + "unindexed endpoint renders '-'" + ); } // [unit->REQ-PICKER-PROJECT-HISTORY-TRUTH] the derivation: sessions.log cwds @@ -1348,15 +1487,45 @@ mod tests { fn project_refs_from_unions_fresh_origin_and_store_branches() { let owlery = Path::new("C:/Users/x/spt-core/owlery"); // Fresh: empty ledger, origin cwd = the created-in project. - let fresh = project_refs_from(&[], Some("C:/Users/x/Documents/projects/spt-core"), vec![], owlery, folder_derive); - assert_eq!(fresh.iter().map(|r| r.id.clone()).collect::>(), vec!["spt-core"]); + let fresh = project_refs_from( + &[], + Some("C:/Users/x/Documents/projects/spt-core"), + vec![], + owlery, + folder_derive, + ); + assert_eq!( + fresh.iter().map(|r| r.id.clone()).collect::>(), + vec!["spt-core"] + ); // A psyche-host fresh perch (owlery-internal origin) has NO phantom project. - let psyche = project_refs_from(&[], Some("C:/Users/x/spt-core/owlery/hall-a/nested/hall-a-psyche"), vec![], owlery, folder_derive); - assert!(psyche.is_empty(), "an owlery-internal origin is not a project"); + let psyche = project_refs_from( + &[], + Some("C:/Users/x/spt-core/owlery/hall-a/nested/hall-a-psyche"), + vec![], + owlery, + folder_derive, + ); + assert!( + psyche.is_empty(), + "an owlery-internal origin is not a project" + ); // Store-only projects union after the session/origin ids, with an empty dir. - let unioned = project_refs_from(&[sess("C:/p/alpha")], None, vec!["beta".into()], owlery, folder_derive); - assert_eq!(unioned.iter().map(|r| r.id.clone()).collect::>(), vec!["alpha", "beta"]); - assert_eq!(unioned[1].dir, "", "a store-only project carries no session dir"); + let unioned = project_refs_from( + &[sess("C:/p/alpha")], + None, + vec!["beta".into()], + owlery, + folder_derive, + ); + assert_eq!( + unioned.iter().map(|r| r.id.clone()).collect::>(), + vec!["alpha", "beta"] + ); + assert_eq!( + unioned[1].dir, "", + "a store-only project carries no session dir" + ); } // [unit->REQ-PICKER-PROJECT-DISPLAY-NAME] the pure display render: a ref shows its @@ -1374,14 +1543,22 @@ mod tests { // A1: the slug id stays the key, but the RENDER is the friendly display — // an operator sees "spt-core", never "github-com-sabermage-spt-core". let a1 = [ - pr("github-com-sabermage-spt-core", "C:/x/projects/spt-core", "spt-core"), + pr( + "github-com-sabermage-spt-core", + "C:/x/projects/spt-core", + "spt-core", + ), pr("github-com-sabermage-owl", "C:/x/owl", "owl"), ]; assert_eq!(disambiguate_project_ids(&a1), vec!["spt-core", "owl"]); // Collision on the DISPLAY (two different repos both named spt-core, different // parents) → parent-folder suffix (one at a drive root). let coll = [ - pr("github-com-a-spt-core", "C:/x/projects/spt-core", "spt-core"), + pr( + "github-com-a-spt-core", + "C:/x/projects/spt-core", + "spt-core", + ), pr("github-com-b-spt-core", "D:/spt-core", "spt-core"), ]; assert_eq!( @@ -1389,22 +1566,36 @@ mod tests { vec!["spt-core (projects)", "spt-core (D:)"] ); // Drive-only: both dirs at a root → the drive letter disambiguates. - let drive = [ - pr("a", "C:/proj", "proj"), - pr("b", "D:/proj", "proj"), - ]; - assert_eq!(disambiguate_project_ids(&drive), vec!["proj (C:)", "proj (D:)"]); + let drive = [pr("a", "C:/proj", "proj"), pr("b", "D:/proj", "proj")]; + assert_eq!( + disambiguate_project_ids(&drive), + vec!["proj (C:)", "proj (D:)"] + ); // Store-only ref (no dir) → display == id verbatim (honest slug fallback). let store_only = [pr("github-com-x-ghost", "", "github-com-x-ghost")]; - assert_eq!(disambiguate_project_ids(&store_only), vec!["github-com-x-ghost"]); + assert_eq!( + disambiguate_project_ids(&store_only), + vec!["github-com-x-ghost"] + ); // C-1 (REMOTE-TRUTH): two refs sharing a display AND the SAME dir are NOT a real // collision — counting raw occurrences mis-fired a suffix (the endpoint-list path // collides a one-dir-per-endpoint cell with itself). Distinct-dir count = 1 → both bare. let same_dir = [ - pr("github-com-a-spt-core", "C:/x/projects/spt-core", "spt-core"), - pr("github-com-b-spt-core", "C:/x/projects/spt-core", "spt-core"), + pr( + "github-com-a-spt-core", + "C:/x/projects/spt-core", + "spt-core", + ), + pr( + "github-com-b-spt-core", + "C:/x/projects/spt-core", + "spt-core", + ), ]; - assert_eq!(disambiguate_project_ids(&same_dir), vec!["spt-core", "spt-core"]); + assert_eq!( + disambiguate_project_ids(&same_dir), + vec!["spt-core", "spt-core"] + ); } // [unit->REQ-PICKER-4] the `driven_by` controller pin renders the node NAME, @@ -1429,9 +1620,15 @@ mod tests { // No label for this key ⇒ truncated `keyprefix…` form, still not the full hex. let other_hex = "deadbeef9876cafef00d"; let bare = driven_by_display(Some(other_hex), &node_labels).unwrap(); - assert!(bare.contains('…'), "should be the truncated keyprefix form: {bare}"); + assert!( + bare.contains('…'), + "should be the truncated keyprefix form: {bare}" + ); assert_ne!(bare, other_hex, "must not leak the bare full key-hex"); - assert!(bare.len() < other_hex.len(), "truncated, shorter than raw hex: {bare}"); + assert!( + bare.len() < other_hex.len(), + "truncated, shorter than raw hex: {bare}" + ); } // [unit->REQ-RUN-PICKER-HOME] home_subnet_options returns the node's member @@ -1443,9 +1640,15 @@ mod tests { let _home = crate::testutil::isolated_home(); let mut store = spt_store::subnet::SubnetStore::default(); - store.create_subnet("alpha", spt_store::access::Mode::Open).unwrap(); - store.create_subnet("bravo", spt_store::access::Mode::Open).unwrap(); - store.create_subnet("charlie", spt_store::access::Mode::Open).unwrap(); + store + .create_subnet("alpha", spt_store::access::Mode::Open) + .unwrap(); + store + .create_subnet("bravo", spt_store::access::Mode::Open) + .unwrap(); + store + .create_subnet("charlie", spt_store::access::Mode::Open) + .unwrap(); store.save().unwrap(); // No MRU recorded yet → all three members present (creation order). diff --git a/crates/spt/src/picker/mod.rs b/crates/spt/src/picker/mod.rs index f53da0a0..4d4cf96f 100644 --- a/crates/spt/src/picker/mod.rs +++ b/crates/spt/src/picker/mod.rs @@ -101,7 +101,11 @@ fn setup_terminal() -> io::Result { // path (run() → setup_terminal); the non-interactive REQ-HOST-RUN-1 flow never // reaches here, so a headless invocation never retitles the operator's terminal. // [impl->REQ-PICKER-WINDOW-TITLE] - crossterm::execute!(stdout, SetTitle("SPT Endpoint Picker"), EnterAlternateScreen)?; + crossterm::execute!( + stdout, + SetTitle("SPT Endpoint Picker"), + EnterAlternateScreen + )?; Terminal::new(CrosstermBackend::new(stdout)) } @@ -371,9 +375,7 @@ fn handle_confirm_key(model: &mut PickerModel, code: KeyCode) -> Option KeyCode::Char('s') if model.launch_keys_live() => { return model.confirm_terminal(ConfirmOption::Shortcut) } - KeyCode::Char('h') if model.launch_keys_live() => { - return model.start_headless_outcome() - } + KeyCode::Char('h') if model.launch_keys_live() => return model.start_headless_outcome(), KeyCode::Enter => { let opt = model.selected_confirm()?; return match opt { @@ -614,7 +616,10 @@ mod tests { #[test] fn purge_outcomes_convert_to_flash_lines() { use crate::cli::PurgeOutcome as O; - assert_eq!(purge_failure_flash(&O::RefusedOnline), "! purge refused: endpoint is online"); + assert_eq!( + purge_failure_flash(&O::RefusedOnline), + "! purge refused: endpoint is online" + ); assert_eq!( purge_failure_flash(&O::RefusedOwnEndpoint), "! purge refused: this session's own endpoint" @@ -629,7 +634,9 @@ mod tests { // the picker closes it is the operator's only handle to the tree whose // records purge deliberately kept. assert_eq!( - purge_failure_flash(&O::RefusedSurvivor { root_pid: Some(4242) }), + purge_failure_flash(&O::RefusedSurvivor { + root_pid: Some(4242) + }), "! purge refused: session still running (root pid 4242)" ); assert_eq!( @@ -657,7 +664,9 @@ mod tests { model.screen = Screen::ConfirmPurge; let mut terminal = Terminal::new(TestBackend::new(80, 24)).expect("test terminal"); - terminal.draw(|f| view::render(&model, f)).expect("draw ConfirmPurge"); + terminal + .draw(|f| view::render(&model, f)) + .expect("draw ConfirmPurge"); // OUT-OF-BAND display mutation: write cells straight through the // BACKEND (bypassing Terminal's diff bookkeeping) — physically what @@ -678,7 +687,9 @@ mod tests { model.remove_endpoint("aa"); model.screen = Screen::PickExisting; terminal.clear().expect("baseline reset"); - terminal.draw(|f| view::render(&model, f)).expect("draw PickExisting"); + terminal + .draw(|f| view::render(&model, f)) + .expect("draw PickExisting"); // A fresh terminal rendering the same model = the complete target screen. let mut fresh = Terminal::new(TestBackend::new(80, 24)).expect("fresh terminal"); @@ -724,7 +735,11 @@ mod tests { // Empty buffer: STILL no nav (deliberate — Esc backs out). m.id_buffer.clear(); assert_eq!(handle_key(&mut m, KeyCode::Backspace), None); - assert_eq!(m.screen, Screen::CreateId, "no empty-buffer fallthrough to back()"); + assert_eq!( + m.screen, + Screen::CreateId, + "no empty-buffer fallthrough to back()" + ); // Filter mode: shortens the query, stays filtering on the list. let mut m2 = model_on_pick(); diff --git a/crates/spt/src/picker/model.rs b/crates/spt/src/picker/model.rs index b2d9bce4..a114cadf 100644 --- a/crates/spt/src/picker/model.rs +++ b/crates/spt/src/picker/model.rs @@ -106,9 +106,10 @@ impl EpDisplay { // Hollow ▢: node down (Offline) or no control seat (HarnessOnly). EpDisplay::Offline | EpDisplay::HarnessOnly => glyph::OFFLINE, // Everything actionable is filled ■. - EpDisplay::Online | EpDisplay::Suspended | EpDisplay::Controlled | EpDisplay::Unbound => { - glyph::ONLINE - } + EpDisplay::Online + | EpDisplay::Suspended + | EpDisplay::Controlled + | EpDisplay::Unbound => glyph::ONLINE, } } @@ -120,10 +121,10 @@ impl EpDisplay { pub fn ansi_color_code(self) -> &'static str { match self { EpDisplay::Offline | EpDisplay::Suspended => "90", // bright black (dark gray) - EpDisplay::Online => "32", // green - EpDisplay::HarnessOnly => "93", // bright yellow ≈ amber - EpDisplay::Controlled => "34", // blue - EpDisplay::Unbound => "31", // red + EpDisplay::Online => "32", // green + EpDisplay::HarnessOnly => "93", // bright yellow ≈ amber + EpDisplay::Controlled => "34", // blue + EpDisplay::Unbound => "31", // red } } @@ -915,7 +916,11 @@ impl PickerModel { // jumps straight into create-new. let adapter_cursor = prefill_adapter .as_deref() - .and_then(|a| adapter_rows.iter().position(|r| r.address() == a || r.adapter == a)) + .and_then(|a| { + adapter_rows + .iter() + .position(|r| r.address() == a || r.adapter == a) + }) .unwrap_or(0); // W4 UX: a bare picker OPENS on Pick-existing (the common case — most runs // re-attach an existing endpoint); `n` jumps to Create-new and Esc backs to @@ -1088,7 +1093,10 @@ impl PickerModel { // ── Pick-existing: category + list ─────────────────────────────────── /// Cycle the category ring left (-1) or right (+1); resets the item cursor. pub fn move_category(&mut self, delta: isize) { - let cur = Category::ALL.iter().position(|c| *c == self.category).unwrap_or(0); + let cur = Category::ALL + .iter() + .position(|c| *c == self.category) + .unwrap_or(0); let len = Category::ALL.len() as isize; let next = ((cur as isize + delta) % len + len) % len; // category wraps self.category = Category::ALL[next as usize]; @@ -1135,9 +1143,7 @@ impl PickerModel { // map matched names back to their endpoint indices, score order scored .into_iter() - .filter_map(|(name, _)| { - idx.iter().copied().find(|&i| self.endpoints[i].id == name) - }) + .filter_map(|(name, _)| idx.iter().copied().find(|&i| self.endpoints[i].id == name)) .collect() } @@ -1383,12 +1389,18 @@ impl PickerModel { // the headless escape, see [`start_headless_outcome`](Self::start_headless_outcome)). // Attach = Control intent. ConfirmOption::Attach | ConfirmOption::Start => Some(if online { - Outcome::Attach { id: ep.id.clone(), intent: AttachIntent::Control } + Outcome::Attach { + id: ep.id.clone(), + intent: AttachIntent::Control, + } } else { bringup(RunMode::Attach) }), ConfirmOption::View => Some(if online { - Outcome::Attach { id: ep.id.clone(), intent: AttachIntent::Viewer } + Outcome::Attach { + id: ep.id.clone(), + intent: AttachIntent::Viewer, + } } else { bringup(RunMode::View) }), @@ -1451,7 +1463,9 @@ impl PickerModel { } pub fn resume_rows(&self) -> &[ResumeRow] { - self.selected_endpoint().map(|e| e.resume_rows.as_slice()).unwrap_or(&[]) + self.selected_endpoint() + .map(|e| e.resume_rows.as_slice()) + .unwrap_or(&[]) } pub fn move_resume(&mut self, delta: isize) { @@ -1496,7 +1510,11 @@ impl PickerModel { resume_adapter: row.adapter.clone(), cwd, subnet: None, // existing perch — home immutable (REQ-RUN-PICKER-HOME) - mode: if headless { RunMode::Start } else { RunMode::Attach }, + mode: if headless { + RunMode::Start + } else { + RunMode::Attach + }, }) } @@ -1582,7 +1600,11 @@ impl PickerModel { resume_adapter: None, cwd, subnet: None, // existing perch — home immutable (REQ-RUN-PICKER-HOME) - mode: if headless { RunMode::Start } else { RunMode::Attach }, + mode: if headless { + RunMode::Start + } else { + RunMode::Attach + }, }) } @@ -1592,7 +1614,9 @@ impl PickerModel { /// bringup core. `keep_id` carries the existing endpoint's id forward. pub fn reenter_create(&mut self, keep_id: bool) { let id = if keep_id { - self.selected_endpoint().map(|e| e.id.clone()).unwrap_or_default() + self.selected_endpoint() + .map(|e| e.id.clone()) + .unwrap_or_default() } else { String::new() }; @@ -1716,7 +1740,11 @@ mod tests { node: "n".to_string(), // Remote test rows carry a raw node hex (the C-2 Wake qualifier); local // rows carry none (Wake is remote-only). - node_key: if is_local { String::new() } else { "nodehex01".to_string() }, + node_key: if is_local { + String::new() + } else { + "nodehex01".to_string() + }, status, is_local, adapter_profile: "claude-spt".to_string(), @@ -1763,7 +1791,10 @@ mod tests { for c in reserved.chars() { m.id_push(c); } - let err = m.id_error.clone().expect("the reserved id must not validate"); + let err = m + .id_error + .clone() + .expect("the reserved id must not validate"); assert!( err.contains(reserved) && err.contains("spt rc"), "the picker shows the reserved-id refusal, naming the one entry: {err}" @@ -1842,8 +1873,12 @@ mod tests { #[test] fn ep_display_glyph_and_square_palette() { // Filled (actionable): online, suspended (wake), controlled, unbound. - for d in [EpDisplay::Online, EpDisplay::Suspended, EpDisplay::Controlled, EpDisplay::Unbound] - { + for d in [ + EpDisplay::Online, + EpDisplay::Suspended, + EpDisplay::Controlled, + EpDisplay::Unbound, + ] { assert_eq!(d.glyph(), glyph::ONLINE, "{d:?} is filled (actionable)"); } // Hollow (cannot act): offline (node down), harness-only (no broker seat). @@ -1853,7 +1888,10 @@ mod tests { // square(false) = bare glyph, no escapes; square(true) = SGR-wrapped. assert_eq!(EpDisplay::Online.square(false), glyph::ONLINE); let colored = EpDisplay::Online.square(true); - assert!(colored.starts_with("\x1b[32m") && colored.ends_with("\x1b[0m"), "{colored:?}"); + assert!( + colored.starts_with("\x1b[32m") && colored.ends_with("\x1b[0m"), + "{colored:?}" + ); assert!(colored.contains(glyph::ONLINE)); } @@ -1881,8 +1919,16 @@ mod tests { // Confirm, live once on the choose rows. let mut e2 = ep("hist", "g", EpStatus::Offline, true); e2.project_refs = vec![ - ProjectRef { id: "a".into(), dir: "/p/a".into(), display: "a".into() }, - ProjectRef { id: "b".into(), dir: "/p/b".into(), display: "b".into() }, + ProjectRef { + id: "a".into(), + dir: "/p/a".into(), + display: "a".into(), + }, + ProjectRef { + id: "b".into(), + dir: "/p/b".into(), + display: "b".into(), + }, ]; let mut m2 = PickerModel::new("p".into(), vec![], vec![e2], None, None, vec![]); m2.screen = Screen::PickExisting; @@ -1890,7 +1936,10 @@ mod tests { m2.run_cwd = "/here".into(); m2.enter_pick(); assert!(matches!(m2.selected_confirm(), Some(ConfirmOption::Start))); - assert!(!m2.launch_keys_live(), "Start that diverts to choose → dead on Confirm"); + assert!( + !m2.launch_keys_live(), + "Start that diverts to choose → dead on Confirm" + ); assert!(m2.enter_choose_project_if_warranted()); assert!(m2.launch_keys_live(), "Choose-project row → live"); // choose `s` writes the endpoint's launcher, for the endpoint the @@ -1940,9 +1989,21 @@ mod tests { #[test] fn change_adapter_picks_and_returns_to_confirm() { let rows = vec![ - AdapterOption { adapter: "claude-spt".into(), profile: None, is_leaf: false }, - AdapterOption { adapter: "claude-spt".into(), profile: Some("fast".into()), is_leaf: true }, - AdapterOption { adapter: "codex".into(), profile: None, is_leaf: false }, + AdapterOption { + adapter: "claude-spt".into(), + profile: None, + is_leaf: false, + }, + AdapterOption { + adapter: "claude-spt".into(), + profile: Some("fast".into()), + is_leaf: true, + }, + AdapterOption { + adapter: "codex".into(), + profile: None, + is_leaf: false, + }, ]; let mut e = ep("agent", "g", EpStatus::Offline, true); e.adapter_profile = "claude-spt".into(); @@ -2002,7 +2063,11 @@ mod tests { "suspended → gray-FILLED, not offline" ); e.status = EpStatus::Offline; - assert_eq!(e.display_status(), EpDisplay::Offline, "offline → gray-hollow"); + assert_eq!( + e.display_status(), + EpDisplay::Offline, + "offline → gray-hollow" + ); assert_ne!(EpStatus::Suspended, EpStatus::Offline); assert_eq!(EpDisplay::Suspended.label(), "SUSPENDED"); } @@ -2037,8 +2102,15 @@ mod tests { "BOX".into(), None, ); - assert_eq!(full.adapter_profile, "claude-spt:doyle", "adapter from gossip, not the blurb"); - assert_eq!(full.project_history, vec!["spt-core", "owl"], "history from gossiped projects"); + assert_eq!( + full.adapter_profile, "claude-spt:doyle", + "adapter from gossip, not the blurb" + ); + assert_eq!( + full.project_history, + vec!["spt-core", "owl"], + "history from gossiped projects" + ); assert!(full.controlled, "controlled read verbatim from gossip"); assert!(full.driven_by.is_none(), "no gossiped driver → no pin"); assert_eq!( @@ -2046,12 +2118,21 @@ mod tests { EpDisplay::Controlled, "controlled=true → blue even with no gossiped driver (the #4 decouple)" ); - assert_eq!(full.description, "a yellow-pages blurb", "the blurb stays the description"); + assert_eq!( + full.description, "a yellow-pages blurb", + "the blurb stays the description" + ); // N-1 pre-field row: degrades clean — empty adapter/history, not controlled. let bare = EndpointRow::from_resource_row(&row(None, &[], false), "BOX".into(), None); - assert!(bare.adapter_profile.is_empty(), "pre-field adapter → empty (renders '-')"); - assert!(bare.project_history.is_empty(), "pre-field projects → empty"); + assert!( + bare.adapter_profile.is_empty(), + "pre-field adapter → empty (renders '-')" + ); + assert!( + bare.project_history.is_empty(), + "pre-field projects → empty" + ); assert!(!bare.controlled, "pre-field row → not controlled"); } @@ -2065,7 +2146,11 @@ mod tests { let mut s = ep("x", "g", EpStatus::Suspended, false); s.is_unbound = true; // ignored once suspended s.driven_by = Some("n".into()); - assert_eq!(s.display_status(), EpDisplay::Suspended, "suspended wins over unbound/controlled"); + assert_eq!( + s.display_status(), + EpDisplay::Suspended, + "suspended wins over unbound/controlled" + ); let off = ep("x", "g", EpStatus::Offline, false); assert_eq!(off.display_status(), EpDisplay::Offline); @@ -2078,7 +2163,10 @@ mod tests { // bound + free + controllable live → green Online. assert_eq!(online(&|e| e.controllable = Some(true)), EpDisplay::Online); // bound + controlled → blue Controlled. - assert_eq!(online(&|e| e.driven_by = Some("n".into())), EpDisplay::Controlled); + assert_eq!( + online(&|e| e.driven_by = Some("n".into())), + EpDisplay::Controlled + ); // #3 (REQ-PICKER-CONTROLLED-LOCAL): a LOCALLY-SPAWN-controlled endpoint has // driven_by=None (the by=None dispatch_spawn case) + controlled=true → STILL blue // Controlled in its own node's picker. Keying on driven_by alone (the bug) @@ -2126,7 +2214,11 @@ mod tests { assert_eq!(e.display_status(), EpDisplay::HarnessOnly); // A legacy live agent (controllable unknown) is also amber (self-corrects). e.controllable = None; - assert_eq!(e.display_status(), EpDisplay::HarnessOnly, "legacy None → amber"); + assert_eq!( + e.display_status(), + EpDisplay::HarnessOnly, + "legacy None → amber" + ); // A controllable (spt-hosted) live agent → green. e.controllable = Some(true); assert_eq!(e.display_status(), EpDisplay::Online); @@ -2134,14 +2226,22 @@ mod tests { // A controlled endpoint → blue, outranking harness-only. e.controllable = Some(false); e.driven_by = Some("cafe".into()); - assert_eq!(e.display_status(), EpDisplay::Controlled, "driven_by → blue"); + assert_eq!( + e.display_status(), + EpDisplay::Controlled, + "driven_by → blue" + ); // A NON-live online endpoint (gateway) is never amber — green, even with // controllable == Some(false)/None. let mut gw = ep("gw", "g", EpStatus::Online, true); gw.endpoint_type = "gateway".into(); gw.controllable = None; - assert_eq!(gw.display_status(), EpDisplay::Online, "gateway never amber"); + assert_eq!( + gw.display_status(), + EpDisplay::Online, + "gateway never amber" + ); gw.controllable = Some(false); assert_eq!(gw.display_status(), EpDisplay::Online); @@ -2166,7 +2266,11 @@ mod tests { let mut e = ep("u", "g", EpStatus::Online, true); e.is_unbound = true; e.controllable = Some(false); // would be HarnessOnly if not unbound - assert_eq!(e.display_status(), EpDisplay::Unbound, "unbound → red, not amber"); + assert_eq!( + e.display_status(), + EpDisplay::Unbound, + "unbound → red, not amber" + ); // A node driving the unbound endpoint still renders Unbound (the dropped // UnboundControlled is absorbed — W5 palette). @@ -2182,7 +2286,11 @@ mod tests { // → Offline. (The old test asserted Offline for status=Offline+is_unbound, // which encoded an impossible combo AND the masking bug — removed.) let dead = ep("d", "g", EpStatus::Offline, true); // is_unbound defaults false - assert_eq!(dead.display_status(), EpDisplay::Offline, "a real offline → gray"); + assert_eq!( + dead.display_status(), + EpDisplay::Offline, + "a real offline → gray" + ); // A plain online row with the unbound flag clear is unaffected. let plain = ep("p", "g", EpStatus::Online, true); @@ -2223,7 +2331,10 @@ mod tests { adapter: None, }; let t = with_proj.title(); - assert!(t.starts_with("spt-core - "), "project head + ` - ` sep: {t}"); + assert!( + t.starts_with("spt-core - "), + "project head + ` - ` sep: {t}" + ); assert!(t.ends_with(" (…12345)"), "trailing …id5: {t}"); assert!( t.contains("AM") || t.contains("PM"), @@ -2267,7 +2378,11 @@ mod tests { None, vec![], ); - assert_eq!(m.screen, Screen::PickExisting, "bare picker opens on Pick-existing"); + assert_eq!( + m.screen, + Screen::PickExisting, + "bare picker opens on Pick-existing" + ); m.screen = Screen::Kind; // jump back to the Layer-1 menu m.kind_cursor = 0; m.enter_kind(); @@ -2322,7 +2437,11 @@ mod tests { let mut m = PickerModel::new("p".into(), vec![], vec![], None, None, vec![]); assert_eq!(m.category, Category::Project); m.move_category(-1); - assert_eq!(m.category, Category::Subnet, "left from first wraps to last"); + assert_eq!( + m.category, + Category::Subnet, + "left from first wraps to last" + ); m.move_category(1); assert_eq!(m.category, Category::Project); } @@ -2385,14 +2504,26 @@ mod tests { m.category = Category::Local; m.enter_pick(); let opts = m.confirm_options(); - assert!(opts.contains(&ConfirmOption::Resume), "offline+local+ledger ⇒ Resume"); - assert!(opts.contains(&ConfirmOption::ChangeAdapter), "offline ⇒ ChangeAdapter"); - assert!(!opts.contains(&ConfirmOption::Instantiate), "local ⇒ no Instantiate"); + assert!( + opts.contains(&ConfirmOption::Resume), + "offline+local+ledger ⇒ Resume" + ); + assert!( + opts.contains(&ConfirmOption::ChangeAdapter), + "offline ⇒ ChangeAdapter" + ); + assert!( + !opts.contains(&ConfirmOption::Instantiate), + "local ⇒ no Instantiate" + ); assert!(opts.contains(&ConfirmOption::Fork) && opts.contains(&ConfirmOption::Shortcut)); // Offline ⇒ Start (bring up), never a bare Attach (nothing live yet). // [unit->REQ-PICKER-ONLINE-ACTION] assert!(opts.contains(&ConfirmOption::Start), "offline ⇒ Start"); - assert!(!opts.contains(&ConfirmOption::Attach), "offline ⇒ no bare Attach"); + assert!( + !opts.contains(&ConfirmOption::Attach), + "offline ⇒ no bare Attach" + ); // online local: no Resume, no ChangeAdapter. let online = ep("b", "g", EpStatus::Online, true); @@ -2431,13 +2562,22 @@ mod tests { m.category = Category::Subnet; m.enter_pick(); let opts = m.confirm_options(); - assert!(opts.contains(&ConfirmOption::Wake), "remote suspended ⇒ Wake now"); - assert!(!opts.contains(&ConfirmOption::Start), "remote suspended ⇒ NO local Start"); + assert!( + opts.contains(&ConfirmOption::Wake), + "remote suspended ⇒ Wake now" + ); + assert!( + !opts.contains(&ConfirmOption::Start), + "remote suspended ⇒ NO local Start" + ); assert!( !opts.contains(&ConfirmOption::ChangeAdapter), "remote suspended ⇒ NO ChangeAdapter (co-gate b: it writes a LOCAL record)" ); - assert!(opts.contains(&ConfirmOption::Instantiate), "remote ⇒ Instantiate survives"); + assert!( + opts.contains(&ConfirmOption::Instantiate), + "remote ⇒ Instantiate survives" + ); assert!(opts.contains(&ConfirmOption::Fork) && opts.contains(&ConfirmOption::Shortcut)); } @@ -2471,11 +2611,23 @@ mod tests { m.category = Category::Local; m.enter_pick(); let opts = m.confirm_options(); - assert!(opts.contains(&ConfirmOption::Start), "local offline ⇒ Start (unchanged)"); - assert!(!opts.contains(&ConfirmOption::Wake), "local offline ⇒ NO Wake"); - assert!(opts.contains(&ConfirmOption::ChangeAdapter), "local offline ⇒ ChangeAdapter kept"); assert!( - matches!(m.confirm_terminal(ConfirmOption::Start), Some(Outcome::Run { .. })), + opts.contains(&ConfirmOption::Start), + "local offline ⇒ Start (unchanged)" + ); + assert!( + !opts.contains(&ConfirmOption::Wake), + "local offline ⇒ NO Wake" + ); + assert!( + opts.contains(&ConfirmOption::ChangeAdapter), + "local offline ⇒ ChangeAdapter kept" + ); + assert!( + matches!( + m.confirm_terminal(ConfirmOption::Start), + Some(Outcome::Run { .. }) + ), "local Start ⇒ local bringup (Outcome::Run), never Wake" ); } @@ -2495,7 +2647,15 @@ mod tests { m.id_push(c); } match m.create_outcome().unwrap() { - Outcome::Run { adapter, id, resume, resume_adapter: _, cwd: _, subnet, mode } => { + Outcome::Run { + adapter, + id, + resume, + resume_adapter: _, + cwd: _, + subnet, + mode, + } => { assert_eq!(adapter, "claude-spt:fast"); assert_eq!(id, "doyle"); assert_eq!(resume, None); @@ -2529,8 +2689,15 @@ mod tests { // immediately; a lone entry whose dir differs (A) or any >1 history (B) offers. #[test] fn should_offer_project_choice_fire_conditions() { - let pr = |id: &str, dir: &str| ProjectRef { id: id.into(), dir: dir.into(), display: id.into() }; - assert!(!should_offer_project_choice("/here", &[]), "no history → start"); + let pr = |id: &str, dir: &str| ProjectRef { + id: id.into(), + dir: dir.into(), + display: id.into(), + }; + assert!( + !should_offer_project_choice("/here", &[]), + "no history → start" + ); assert!( !should_offer_project_choice("/here", &[pr("a", "/here")]), "lone entry already at run cwd → no choice" @@ -2556,14 +2723,21 @@ mod tests { // "(CURRENT DIR)" marker instead (A-2). No history → empty. #[test] fn build_project_choices_head_here_rest() { - let pr = |id: &str, dir: &str| ProjectRef { id: id.into(), dir: dir.into(), display: id.into() }; + let pr = |id: &str, dir: &str| ProjectRef { + id: id.into(), + dir: dir.into(), + display: id.into(), + }; let hist = vec![pr("recent", "/p/recent"), pr("older", "/p/older")]; let ch = build_project_choices("/here", &hist); assert_eq!(ch.len(), 3, "head + current-dir + rest"); assert_eq!(ch[0].cwd, "/p/recent"); // A-3: the not-in-history current-dir row reads "CURRENT DIR --> " // (folder tail of the run cwd), NOT the old "Here: ". - assert_eq!(ch[1].label, "CURRENT DIR --> here", "current-dir row, folder tail"); + assert_eq!( + ch[1].label, "CURRENT DIR --> here", + "current-dir row, folder tail" + ); assert_eq!(ch[1].cwd, "/here"); assert_eq!(ch[2].cwd, "/p/older", "rest newest→oldest"); // Run cwd IS the head dir → no separate current-dir row; the head SELF-IDENTIFIES. @@ -2574,7 +2748,10 @@ mod tests { "no separate current-dir row when cwd is already a history dir" ); // A-2: the matching history row carries the "(CURRENT DIR)" marker. - assert_eq!(ch2[0].label, "recent (CURRENT DIR)", "head row self-identifies as current"); + assert_eq!( + ch2[0].label, "recent (CURRENT DIR)", + "head row self-identifies as current" + ); assert!(build_project_choices("/here", &[]).is_empty()); // [unit->REQ-PICKER-CHOOSE-DEDUP-ALL] A4: run cwd matches an OLDER (non-head) // history dir → still no separate current-dir row (that project is already the @@ -2588,7 +2765,10 @@ mod tests { assert_eq!(ch3[0].cwd, "/p/recent"); assert_eq!(ch3[1].cwd, "/p/older"); // A-2: the older row that matches the run cwd self-identifies. - assert_eq!(ch3[1].label, "older (CURRENT DIR)", "older row self-identifies as current"); + assert_eq!( + ch3[1].label, "older (CURRENT DIR)", + "older row self-identifies as current" + ); } // [unit->REQ-PICKER-START-PROJECT-CHOICE] "Start now" diverts to the choice @@ -2598,14 +2778,25 @@ mod tests { fn choose_project_outcome_bakes_cwd_and_diverts() { let mut e = ep("agent", "g", EpStatus::Offline, true); e.project_refs = vec![ - ProjectRef { id: "recent".into(), dir: "/p/recent".into(), display: "recent".into() }, - ProjectRef { id: "older".into(), dir: String::new(), display: "older".into() }, + ProjectRef { + id: "recent".into(), + dir: "/p/recent".into(), + display: "recent".into(), + }, + ProjectRef { + id: "older".into(), + dir: String::new(), + display: "older".into(), + }, ]; let mut m = PickerModel::new("p".into(), vec![], vec![e], None, None, vec![]); m.category = Category::Local; m.run_cwd = "/here".into(); m.enter_pick(); - assert!(m.enter_choose_project_if_warranted(), "history>1 warrants the step"); + assert!( + m.enter_choose_project_if_warranted(), + "history>1 warrants the step" + ); assert_eq!(m.screen, Screen::ChooseProject); // Head choice (cursor 0) bakes its recorded dir + attaches by default. match m.choose_project_outcome(false).unwrap() { @@ -2629,13 +2820,21 @@ mod tests { // Skip case: a lone entry already at the run cwd starts immediately (no divert). let mut solo = ep("solo", "g", EpStatus::Offline, true); - solo.project_refs = vec![ProjectRef { id: "recent".into(), dir: "/here".into(), display: "recent".into() }]; + solo.project_refs = vec![ProjectRef { + id: "recent".into(), + dir: "/here".into(), + display: "recent".into(), + }]; let mut m2 = PickerModel::new("p".into(), vec![], vec![solo], None, None, vec![]); m2.category = Category::Local; m2.run_cwd = "/here".into(); m2.enter_pick(); assert!(!m2.enter_choose_project_if_warranted()); - assert_eq!(m2.screen, Screen::Confirm, "no divert → today's immediate start"); + assert_eq!( + m2.screen, + Screen::Confirm, + "no divert → today's immediate start" + ); } // [unit->REQ-RUN-PICKER] confirm terminal actions route correctly: an online @@ -2650,11 +2849,17 @@ mod tests { use spt_net::net::attach::AttachIntent; assert_eq!( m.confirm_terminal(ConfirmOption::Attach), - Some(Outcome::Attach { id: "live".into(), intent: AttachIntent::Control }) + Some(Outcome::Attach { + id: "live".into(), + intent: AttachIntent::Control + }) ); assert_eq!( m.confirm_terminal(ConfirmOption::View), - Some(Outcome::Attach { id: "live".into(), intent: AttachIntent::Viewer }) + Some(Outcome::Attach { + id: "live".into(), + intent: AttachIntent::Viewer + }) ); match m.confirm_terminal(ConfirmOption::Shortcut).unwrap() { Outcome::Shortcut { adapter, id, .. } => { @@ -2713,8 +2918,22 @@ mod tests { fn resume_outcome_bakes_session() { let mut e = ep("cold", "g", EpStatus::Offline, true); e.resume_rows = vec![ - ResumeRow { session_id: "old".into(), ts: "t1".into(), trigger: "boot".into(), project: String::new(), cwd: None, adapter: None }, - ResumeRow { session_id: "new".into(), ts: "t2".into(), trigger: "clear".into(), project: String::new(), cwd: Some("/proj/new".into()), adapter: None }, + ResumeRow { + session_id: "old".into(), + ts: "t1".into(), + trigger: "boot".into(), + project: String::new(), + cwd: None, + adapter: None, + }, + ResumeRow { + session_id: "new".into(), + ts: "t2".into(), + trigger: "clear".into(), + project: String::new(), + cwd: Some("/proj/new".into()), + adapter: None, + }, ]; let mut m = PickerModel::new("p".into(), vec![], vec![e], None, None, vec![]); m.category = Category::Local; @@ -2792,8 +3011,15 @@ mod tests { // re-stamp (Some → the dispatch will re-stamp on a diff). assert_eq!(m.selected_resume().unwrap().session_id, "recorded"); match m.resume_outcome(false).unwrap() { - Outcome::Run { adapter, resume_adapter, .. } => { - assert_eq!(adapter, "claude-spt", "recorded row adapter overrides the endpoint stamp"); + Outcome::Run { + adapter, + resume_adapter, + .. + } => { + assert_eq!( + adapter, "claude-spt", + "recorded row adapter overrides the endpoint stamp" + ); assert_eq!( resume_adapter.as_deref(), Some("claude-spt"), @@ -2810,8 +3036,15 @@ mod tests { m.move_resume(1); assert_eq!(m.selected_resume().unwrap().session_id, "legacy"); match m.resume_outcome(false).unwrap() { - Outcome::Run { adapter, resume_adapter, .. } => { - assert_eq!(adapter, "claude-spt:ccs", "a None-adapter row degrades to the endpoint stamp"); + Outcome::Run { + adapter, + resume_adapter, + .. + } => { + assert_eq!( + adapter, "claude-spt:ccs", + "a None-adapter row degrades to the endpoint stamp" + ); assert_eq!( resume_adapter, None, "a None-adapter row carries NO resume_adapter → dispatch never writes (no clobber)" @@ -2833,9 +3066,15 @@ mod tests { m.category = Category::Local; assert!(!m.purge_key_live(), "online ⇒ x not live"); m.enter_confirm_purge(); - assert_ne!(m.screen, Screen::ConfirmPurge, "online never reaches the confirm"); + assert_ne!( + m.screen, + Screen::ConfirmPurge, + "online never reaches the confirm" + ); assert!( - m.flash.as_deref().is_some_and(|f| f.contains("offline only")), + m.flash + .as_deref() + .is_some_and(|f| f.contains("offline only")), "online ⇒ flash the offline-only gate, got {:?}", m.flash ); @@ -2846,9 +3085,15 @@ mod tests { m2.category = Category::Subnet; assert!(!m2.purge_key_live(), "remote ⇒ x not live"); m2.enter_confirm_purge(); - assert_ne!(m2.screen, Screen::ConfirmPurge, "remote never reaches the confirm"); + assert_ne!( + m2.screen, + Screen::ConfirmPurge, + "remote never reaches the confirm" + ); assert!( - m2.flash.as_deref().is_some_and(|f| f.contains("local endpoints only")), + m2.flash + .as_deref() + .is_some_and(|f| f.contains("local endpoints only")), "remote ⇒ flash the local-only gate, got {:?}", m2.flash ); @@ -2873,9 +3118,15 @@ mod tests { m.category = Category::Local; m.enter_confirm_purge(); assert_eq!(m.screen, Screen::ConfirmPurge); - assert_eq!(m.purge_outcome(), Some(Outcome::Purge { id: "cold".into() })); + assert_eq!( + m.purge_outcome(), + Some(Outcome::Purge { id: "cold".into() }) + ); // Esc rides the shared back(): confirm → list, nothing purged. - assert!(!m.back(), "back never exits the picker from the purge confirm"); + assert!( + !m.back(), + "back never exits the picker from the purge confirm" + ); assert_eq!(m.screen, Screen::PickExisting); } @@ -2910,7 +3161,10 @@ mod tests { m.enter_pick(); m.reenter_create(true); assert_eq!(m.screen, Screen::CreateAdapter); - assert_eq!(m.id_buffer, "cold", "change-adapter/instantiate keep the id"); + assert_eq!( + m.id_buffer, "cold", + "change-adapter/instantiate keep the id" + ); m.reenter_create(false); assert_eq!(m.id_buffer, "", "fork starts a fresh id"); } @@ -2942,7 +3196,11 @@ mod tests { m.id_push(c); } // CreateId Enter on a multi-subnet node advances to the home layer (no yield). - assert_eq!(m.enter_id(), None, "multi-subnet → CreateHome, no immediate outcome"); + assert_eq!( + m.enter_id(), + None, + "multi-subnet → CreateHome, no immediate outcome" + ); assert_eq!(m.screen, Screen::CreateHome); match m.create_outcome().expect("home-layer Enter yields the Run") { Outcome::Run { subnet, id, .. } => { @@ -2959,16 +3217,30 @@ mod tests { #[test] fn single_subnet_skips_home_layer() { let rows = build_adapter_tree(&[info("claude-spt", &[], &[])]); - let mut m = PickerModel::new("p".into(), rows.clone(), vec![], None, None, vec!["solo".into()]); + let mut m = PickerModel::new( + "p".into(), + rows.clone(), + vec![], + None, + None, + vec!["solo".into()], + ); m.screen = Screen::CreateId; for c in "doyle".chars() { m.id_push(c); } - match m.enter_id().expect("single-subnet → Run directly, no home layer") { + match m + .enter_id() + .expect("single-subnet → Run directly, no home layer") + { Outcome::Run { subnet, .. } => assert_eq!(subnet, None, "layer skipped → subnet None"), o => panic!("expected Run, got {o:?}"), } - assert_eq!(m.screen, Screen::CreateId, "no CreateHome on a single-subnet node"); + assert_eq!( + m.screen, + Screen::CreateId, + "no CreateHome on a single-subnet node" + ); assert_eq!(m.selected_home(), None); // zero subnets (unpaired) likewise skips the layer. @@ -2984,7 +3256,11 @@ mod tests { #[test] fn home_selection_bakes_into_run_subnet() { let rows = build_adapter_tree(&[info("claude-spt", &[], &[])]); - let homes = vec!["bignet".to_string(), "homenet".to_string(), "labnet".to_string()]; + let homes = vec![ + "bignet".to_string(), + "homenet".to_string(), + "labnet".to_string(), + ]; let mut m = PickerModel::new("p".into(), rows, vec![], None, None, homes); m.screen = Screen::CreateId; for c in "doyle".chars() { @@ -2999,7 +3275,11 @@ mod tests { o => panic!("expected Run, got {o:?}"), } m.move_home(5); // clamps at the last entry, never wraps - assert_eq!(m.selected_home(), Some("labnet".into()), "home cursor clamps at the end"); + assert_eq!( + m.selected_home(), + Some("labnet".into()), + "home cursor clamps at the end" + ); } // [unit->REQ-RUN-PICKER-HOME] Esc backs CreateHome → CreateId, then CreateId → @@ -3012,6 +3292,10 @@ mod tests { assert!(!m.back()); assert_eq!(m.screen, Screen::CreateId, "CreateHome Esc → CreateId"); assert!(!m.back()); - assert_eq!(m.screen, Screen::CreateAdapter, "CreateId Esc → CreateAdapter (unchanged)"); + assert_eq!( + m.screen, + Screen::CreateAdapter, + "CreateId Esc → CreateAdapter (unchanged)" + ); } } diff --git a/crates/spt/src/picker/shortcut.rs b/crates/spt/src/picker/shortcut.rs index 8659c4b3..d87926b3 100644 --- a/crates/spt/src/picker/shortcut.rs +++ b/crates/spt/src/picker/shortcut.rs @@ -208,12 +208,29 @@ mod tests { #[test] fn the_body_is_the_ladder_verb() { let body = render_script(DEFAULT_BASENAME, "doyle"); - assert!(body.contains("spt go doyle"), "the launcher goes to the endpoint: {body}"); - assert!(!body.contains("endpoint run"), "the retired verb is never written again"); - for retired in ["--adapter", "--id", "--create", "--resume", "--start", "--view", "--save"] { + assert!( + body.contains("spt go doyle"), + "the launcher goes to the endpoint: {body}" + ); + assert!( + !body.contains("endpoint run"), + "the retired verb is never written again" + ); + for retired in [ + "--adapter", + "--id", + "--create", + "--resume", + "--start", + "--view", + "--save", + ] { assert!(!body.contains(retired), "no baked selection: {retired}"); } - assert!(has_sentinel(&body), "sentinel rides a comment line near the top"); + assert!( + has_sentinel(&body), + "sentinel rides a comment line near the top" + ); assert!(!is_stale(&body), "what we write now is never stale"); // harness-agnostic spt-core emits `spt-`, NEVER `cc-`. assert!(body.contains("spt-doyle")); @@ -226,11 +243,19 @@ mod tests { fn basename_is_parameterized() { assert_eq!( shortcut_filename(DEFAULT_BASENAME, "doyle"), - if cfg!(windows) { "spt-doyle.cmd" } else { "spt-doyle" } + if cfg!(windows) { + "spt-doyle.cmd" + } else { + "spt-doyle" + } ); assert_eq!( shortcut_filename("cc", "doyle"), - if cfg!(windows) { "cc-doyle.cmd" } else { "cc-doyle" } + if cfg!(windows) { + "cc-doyle.cmd" + } else { + "cc-doyle" + } ); let body = render_script("cc", "doyle"); assert!(body.contains("cc-doyle"), "adapter override emits cc-"); @@ -254,8 +279,14 @@ mod tests { assert!(has_sentinel(&prior), "a pre-rename launcher is still ours"); assert!(is_stale(&prior), "...and it is stale"); - assert!(!has_sentinel("#!/bin/sh\necho hi\n"), "a user script has no sentinel"); - assert!(!is_stale("#!/bin/sh\necho hi\n"), "a file that is not ours is not stale"); + assert!( + !has_sentinel("#!/bin/sh\necho hi\n"), + "a user script has no sentinel" + ); + assert!( + !is_stale("#!/bin/sh\necho hi\n"), + "a file that is not ours is not stale" + ); } /// A launcher body as the pre-U3 generator wrote it — the on-disk shape diff --git a/crates/spt/src/picker/view.rs b/crates/spt/src/picker/view.rs index 6b4e3fa4..c8dbdc18 100644 --- a/crates/spt/src/picker/view.rs +++ b/crates/spt/src/picker/view.rs @@ -189,8 +189,9 @@ fn render_create_adapter(model: &PickerModel, f: &mut Frame, area: Rect) { .direction(Direction::Vertical) .constraints([Constraint::Min(1), Constraint::Length(1)]) .split(area); - let list = List::new(adapter_list_items(model)) - .block(titled_block("Choose your harness adapter for this endpoint:")); + let list = List::new(adapter_list_items(model)).block(titled_block( + "Choose your harness adapter for this endpoint:", + )); // [impl->REQ-PICKER-LIST-SCROLL] render_list(f, chunks[0], list, adapter_selected(model)); f.render_widget(legend(), chunks[1]); @@ -205,8 +206,9 @@ fn render_change_adapter(model: &PickerModel, f: &mut Frame, area: Rect) { .direction(Direction::Vertical) .constraints([Constraint::Min(1), Constraint::Length(1)]) .split(area); - let list = List::new(adapter_list_items(model)) - .block(titled_block("Change harness adapter (applies to this endpoint):")); + let list = List::new(adapter_list_items(model)).block(titled_block( + "Change harness adapter (applies to this endpoint):", + )); // [impl->REQ-PICKER-LIST-SCROLL] render_list(f, chunks[0], list, adapter_selected(model)); f.render_widget(legend_text(LEGEND_CHANGE_ADAPTER), chunks[1]); @@ -365,7 +367,9 @@ fn render_pick(model: &PickerModel, f: &mut Frame, area: Rect) { if last_group != Some(ep.group.as_str()) { items.push(ListItem::new(Span::styled( ep.group.clone(), - Style::default().fg(Color::DarkGray).add_modifier(Modifier::DIM), + Style::default() + .fg(Color::DarkGray) + .add_modifier(Modifier::DIM), ))); // Bug #13: list the machine's shared subnets beneath its ONE header // (a machine in >1 shared subnet is a single group, not a duplicate @@ -374,7 +378,9 @@ fn render_pick(model: &PickerModel, f: &mut Frame, area: Rect) { if !ep.subnets.is_empty() { items.push(ListItem::new(Span::styled( format!(" {} {}", glyph::BRANCH, ep.subnets.join(", ")), - Style::default().fg(Color::DarkGray).add_modifier(Modifier::DIM), + Style::default() + .fg(Color::DarkGray) + .add_modifier(Modifier::DIM), ))); } last_group = Some(ep.group.as_str()); @@ -652,7 +658,11 @@ fn render_selection_summary(model: &PickerModel, f: &mut Frame, area: Rect) { fn render_confirm(model: &PickerModel, f: &mut Frame, area: Rect) { let chunks = Layout::default() .direction(Direction::Vertical) - .constraints([Constraint::Length(7), Constraint::Min(1), Constraint::Length(1)]) + .constraints([ + Constraint::Length(7), + Constraint::Min(1), + Constraint::Length(1), + ]) .split(area); render_selection_summary(model, f, chunks[0]); @@ -671,7 +681,10 @@ fn render_confirm(model: &PickerModel, f: &mut Frame, area: Rect) { List::new(items).block(titled_block("Options")), Some(model.confirm_cursor), ); - f.render_widget(bottom(model, launch_legend(LEGEND_CONFIRM, model)), chunks[2]); + f.render_widget( + bottom(model, launch_legend(LEGEND_CONFIRM, model)), + chunks[2], + ); } // ── Choose-project (after "Start now") ────────────────────────────────────── @@ -681,7 +694,11 @@ fn render_confirm(model: &PickerModel, f: &mut Frame, area: Rect) { fn render_choose_project(model: &PickerModel, f: &mut Frame, area: Rect) { let chunks = Layout::default() .direction(Direction::Vertical) - .constraints([Constraint::Length(7), Constraint::Min(1), Constraint::Length(1)]) + .constraints([ + Constraint::Length(7), + Constraint::Min(1), + Constraint::Length(1), + ]) .split(area); render_selection_summary(model, f, chunks[0]); @@ -713,7 +730,11 @@ fn render_choose_project(model: &PickerModel, f: &mut Frame, area: Rect) { fn render_resume(model: &PickerModel, f: &mut Frame, area: Rect) { let chunks = Layout::default() .direction(Direction::Vertical) - .constraints([Constraint::Length(7), Constraint::Min(1), Constraint::Length(1)]) + .constraints([ + Constraint::Length(7), + Constraint::Min(1), + Constraint::Length(1), + ]) .split(area); render_selection_summary(model, f, chunks[0]); @@ -892,8 +913,7 @@ mod tests { adapter: None, }) .collect(); - let mut m = - PickerModel::new("spt-core".into(), vec![], vec![e], None, None, vec![]); + let mut m = PickerModel::new("spt-core".into(), vec![], vec![e], None, None, vec![]); m.screen = Screen::Resume; m.category = Category::Local; m.item_cursor = 0; @@ -941,7 +961,10 @@ mod tests { let mut m2 = PickerModel::new("spt-core".into(), vec![], vec![spt], None, None, vec![]); m2.screen = Screen::PickExisting; m2.category = Category::Local; - assert!(!rendered(&m2).contains("HARNESS ONLY"), "controllable → plain ONLINE"); + assert!( + !rendered(&m2).contains("HARNESS ONLY"), + "controllable → plain ONLINE" + ); // A REMOTE-controlled endpoint → the blue CONTROLLED status line. let mut ctl = ep("driven", EpStatus::Online, true); @@ -976,7 +999,10 @@ mod tests { let mut mc = PickerModel::new("spt-core".into(), vec![], vec![rc], None, None, vec![]); mc.category = Category::Local; mc.screen = Screen::Confirm; - assert!(rendered(&mc).contains("controlled by cafe"), "remote driver names the node"); + assert!( + rendered(&mc).contains("controlled by cafe"), + "remote driver names the node" + ); let mut lc = ep("localdriven2", EpStatus::Online, true); lc.controlled = true; @@ -1002,7 +1028,10 @@ mod tests { mown.category = Category::Local; mown.screen = Screen::Confirm; let out = rendered(&mown); - assert!(out.contains("controlled locally"), "own-node driver reads as local control"); + assert!( + out.contains("controlled locally"), + "own-node driver reads as local control" + ); assert!( !out.contains("controlled by cafe"), "an own-node driver never prints the node name as a foreign driver" @@ -1032,11 +1061,20 @@ mod tests { m4.screen = Screen::PickExisting; m4.category = Category::Local; let s4 = rendered(&m4); - assert!(s4.contains("UNBOUND"), "unbound endpoint shows the UNBOUND state"); - assert!(!s4.contains("HARNESS ONLY"), "unbound is not amber harness-only"); + assert!( + s4.contains("UNBOUND"), + "unbound endpoint shows the UNBOUND state" + ); + assert!( + !s4.contains("HARNESS ONLY"), + "unbound is not amber harness-only" + ); // W5: Unbound is now red-FILLED ■ (rc-attachable = actionable), not hollow. // [unit->REQ-SUBNET-DISPLAY-PARITY] - assert!(s4.contains(glyph::ONLINE), "unbound renders the FILLED ■ square (red, actionable)"); + assert!( + s4.contains(glyph::ONLINE), + "unbound renders the FILLED ■ square (red, actionable)" + ); } // [unit->REQ-RUN-PICKER] the kind screen renders both choices + the caret on @@ -1087,8 +1125,14 @@ mod tests { m.screen = Screen::CreateHome; m.id_buffer = "doyle".into(); let s = rendered(&m); - assert!(s.contains("Anchor subnet for doyle"), "titled with the id: {s}"); - assert!(s.contains("bignet") && s.contains("homenet"), "lists members: {s}"); + assert!( + s.contains("Anchor subnet for doyle"), + "titled with the id: {s}" + ); + assert!( + s.contains("bignet") && s.contains("homenet"), + "lists members: {s}" + ); } // [unit->REQ-RUN-PICKER] pick-existing renders the category tabs, the status @@ -1106,14 +1150,20 @@ mod tests { m.category = Category::Local; m.local_tab_label = "kitsubito".into(); let s = rendered(&m); - assert!(s.contains("kitsubito (here)"), "the local tab names this node: {s}"); + assert!( + s.contains("kitsubito (here)"), + "the local tab names this node: {s}" + ); assert!(s.contains(glyph::ONLINE), "online square"); assert!(s.contains(glyph::OFFLINE), "offline square"); assert!(s.contains("doyle")); // description pane for the highlighted (first) endpoint: assert!(s.contains("claude-spt:fast"), "adapter:profile in the pane"); assert!(s.contains("spt-core"), "project history in the pane"); - assert!(s.contains("the gatekeeper"), "endpoint description in the pane"); + assert!( + s.contains("the gatekeeper"), + "endpoint description in the pane" + ); } // [unit->REQ-RUN-PICKER] an empty category renders the create hint. @@ -1152,7 +1202,10 @@ mod tests { // Offline ⇒ no "View now": a read-only viewer needs a live PTY. // [unit->REQ-PICKER-OFFLINE-NO-VIEW] assert!(!s.contains("View now"), "offline ⇒ no dead View action"); - assert!(s.contains("Resume from history"), "offline+local+ledger ⇒ Resume option"); + assert!( + s.contains("Resume from history"), + "offline+local+ledger ⇒ Resume option" + ); assert!(s.contains("Fork endpoint")); } @@ -1177,8 +1230,14 @@ mod tests { m.category = Category::Local; m.enter_pick(); let s = rendered(&m); - assert!(s.contains("Project history: spt-core"), "friendly display in the confirm panel"); - assert!(!s.contains("github-com-sabermage"), "raw slug never rendered"); + assert!( + s.contains("Project history: spt-core"), + "friendly display in the confirm panel" + ); + assert!( + !s.contains("github-com-sabermage"), + "raw slug never rendered" + ); } // [unit->REQ-PICKER-CHANGE-ADAPTER-FLOW] B-2 (F029): the change-adapter screen @@ -1186,18 +1245,39 @@ mod tests { #[test] fn change_adapter_screen_renders_tree_and_apply_legend() { let rows = vec![ - AdapterOption { adapter: "claude-spt".into(), profile: None, is_leaf: false }, - AdapterOption { adapter: "codex".into(), profile: None, is_leaf: false }, + AdapterOption { + adapter: "claude-spt".into(), + profile: None, + is_leaf: false, + }, + AdapterOption { + adapter: "codex".into(), + profile: None, + is_leaf: false, + }, ]; - let mut m = PickerModel::new("p".into(), rows, vec![ep("agent", EpStatus::Offline, true)], None, None, vec![]); + let mut m = PickerModel::new( + "p".into(), + rows, + vec![ep("agent", EpStatus::Offline, true)], + None, + None, + vec![], + ); m.screen = Screen::PickExisting; m.category = Category::Local; m.enter_pick(); m.enter_change_adapter(); let s = rendered(&m); assert!(s.contains("Change harness adapter"), "change title"); - assert!(s.contains("claude-spt") && s.contains("codex"), "adapter rows"); - assert!(s.contains("enter apply"), "apply legend, not the create legend"); + assert!( + s.contains("claude-spt") && s.contains("codex"), + "adapter rows" + ); + assert!( + s.contains("enter apply"), + "apply legend, not the create legend" + ); } // [unit->REQ-PICKER-KEY-GATE-LAUNCH-CAPABLE] B-1 (F029): the footer renders the @@ -1207,12 +1287,22 @@ mod tests { #[test] fn footer_hints_h_s_only_when_launch_keys_live() { // Offline, no history → "Start now" immediate-start → hints shown. - let mut m = PickerModel::new("p".into(), vec![], vec![ep("a", EpStatus::Offline, true)], None, None, vec![]); + let mut m = PickerModel::new( + "p".into(), + vec![], + vec![ep("a", EpStatus::Offline, true)], + None, + None, + vec![], + ); m.screen = Screen::PickExisting; m.category = Category::Local; m.enter_pick(); let s = rendered(&m); - assert!(s.contains("h headless") && s.contains("s shortcut"), "live → hints shown"); + assert!( + s.contains("h headless") && s.contains("s shortcut"), + "live → hints shown" + ); // Online (controllable) → Attach highlighted → not launch-capable → hidden. let mut online = ep("b", EpStatus::Online, true); @@ -1249,12 +1339,19 @@ mod tests { s.contains("Fork endpoint here --> /work/spt-core"), "fork label names the launch dir" ); - let file = if cfg!(windows) { "spt-doyle.cmd" } else { "spt-doyle" }; + let file = if cfg!(windows) { + "spt-doyle.cmd" + } else { + "spt-doyle" + }; assert!( s.contains(&format!("Set shortcut here --> /work/spt-core/{file}")), "shortcut label names the exact on-disk file" ); - assert!(!s.contains("New/Update spt-"), "old static shortcut label gone"); + assert!( + !s.contains("New/Update spt-"), + "old static shortcut label gone" + ); } // [unit->REQ-PICKER-START-PROJECT-CHOICE] the Choose-project screen keeps the @@ -1265,8 +1362,16 @@ mod tests { use crate::picker::model::ProjectRef; let mut e = ep("doyle", EpStatus::Offline, true); e.project_refs = vec![ - ProjectRef { id: "spt-core".into(), dir: "/p/spt-core".into(), display: "spt-core".into() }, - ProjectRef { id: "owl".into(), dir: "/p/owl".into(), display: "owl".into() }, + ProjectRef { + id: "spt-core".into(), + dir: "/p/spt-core".into(), + display: "spt-core".into(), + }, + ProjectRef { + id: "owl".into(), + dir: "/p/owl".into(), + display: "owl".into(), + }, ]; let mut m = PickerModel::new("p".into(), vec![], vec![e], None, None, vec![]); m.screen = Screen::PickExisting; @@ -1275,10 +1380,19 @@ mod tests { m.enter_pick(); assert!(m.enter_choose_project_if_warranted()); let s = rendered(&m); - assert!(s.contains("Confirm selection"), "TOP Confirm panel retained"); - assert!(s.contains("Choose project:"), "bottom swapped to the choice list"); + assert!( + s.contains("Confirm selection"), + "TOP Confirm panel retained" + ); + assert!( + s.contains("Choose project:"), + "bottom swapped to the choice list" + ); assert!(s.contains("spt-core"), "most-recent project row"); - assert!(s.contains("CURRENT DIR --> here"), "run cwd offered as a distinct dir (A-3 label)"); + assert!( + s.contains("CURRENT DIR --> here"), + "run cwd offered as a distinct dir (A-3 label)" + ); assert!(s.contains("owl"), "older history row"); } @@ -1328,8 +1442,17 @@ mod tests { m.enter_pick(); m.enter_resume(); let s = rendered(&m); - assert!(s.contains("Confirm selection"), "TOP Confirm panel retained"); - assert!(s.contains("Resume from a prior session:"), "bottom swapped to ledger"); - assert!(s.contains("spt-core - "), "a ledger row still renders under it"); + assert!( + s.contains("Confirm selection"), + "TOP Confirm panel retained" + ); + assert!( + s.contains("Resume from a prior session:"), + "bottom swapped to ledger" + ); + assert!( + s.contains("spt-core - "), + "a ledger row still renders under it" + ); } } diff --git a/crates/spt/src/rc.rs b/crates/spt/src/rc.rs index 20d7227f..d814163f 100644 --- a/crates/spt/src/rc.rs +++ b/crates/spt/src/rc.rs @@ -29,8 +29,8 @@ use std::time::{Duration, Instant}; use spt_daemon::attach::{ request_attach_endpoint, send_attach_input, send_attach_resize, send_seal_ceremony_code, }; -use spt_daemon::effect::{Minter, MintedOp}; use spt_daemon::brain::{now_ms, Brain, BrokerEvent}; +use spt_daemon::effect::{MintedOp, Minter}; use spt_daemon::msg::{decode_bytes, SEAL_CEREMONY_ADMITTED, SEAL_CEREMONY_REFUSED}; use spt_net::net::attach::{AttachDecoder, AttachIntent, AttachRecord}; @@ -106,7 +106,11 @@ impl MouseModeScanner { continue; } match parse_decset_private(&buf[i..]) { - DecsetParse::Complete { consumed, params, set } => { + DecsetParse::Complete { + consumed, + params, + set, + } => { for p in params { apply_mouse_mode(mode, p, set); } @@ -133,7 +137,11 @@ impl MouseModeScanner { enum DecsetParse { /// A complete `ESC[?h|l`: the byte length consumed, the numeric /// params, and `set` (`true` for `h`, `false` for `l`). - Complete { consumed: usize, params: Vec, set: bool }, + Complete { + consumed: usize, + params: Vec, + set: bool, + }, /// `ESC[?…` with no final `h`/`l` yet (chunk boundary) — carry + retry. Incomplete, /// `s` does not start a private-mode sequence (`ESC` of something else). @@ -146,7 +154,8 @@ fn parse_decset_private(s: &[u8]) -> DecsetParse { // Need at least `ESC [ ?`. if s.len() < 3 { // Could be the very start of one split across the boundary. - if s.first() == Some(&0x1b) && s.get(1).is_none_or(|&b| b == b'[') + if s.first() == Some(&0x1b) + && s.get(1).is_none_or(|&b| b == b'[') && s.get(2).is_none_or(|&b| b == b'?') { return DecsetParse::Incomplete; @@ -408,7 +417,11 @@ enum ReassertParse { fn parse_reassert_trigger(s: &[u8]) -> ReassertParse { // Alt-screen enter is a private-mode SET — reuse the DECSET parser. match parse_decset_private(s) { - DecsetParse::Complete { consumed, params, set } => { + DecsetParse::Complete { + consumed, + params, + set, + } => { let alt_enter = set && params.iter().any(|&p| matches!(p, 1049 | 47 | 1047)); return if alt_enter { ReassertParse::Fired { consumed } @@ -627,8 +640,7 @@ enum KeyAction { #[cfg(windows)] fn key_event_step(armed: &mut bool, ke: crossterm::event::KeyEvent) -> KeyAction { use crossterm::event::{KeyCode, KeyModifiers}; - let is_ctrl_b = - ke.code == KeyCode::Char('b') && ke.modifiers.contains(KeyModifiers::CONTROL); + let is_ctrl_b = ke.code == KeyCode::Char('b') && ke.modifiers.contains(KeyModifiers::CONTROL); if *armed { *armed = false; if ke.code == KeyCode::Char('d') && ke.modifiers.is_empty() { @@ -847,7 +859,10 @@ impl RawGuard { } #[cfg(windows)] { - RawGuard { raw, prior_out_mode } + RawGuard { + raw, + prior_out_mode, + } } #[cfg(not(windows))] { @@ -897,7 +912,11 @@ struct DisplayGuard { impl DisplayGuard { fn new(out: W, active: bool) -> Self { - DisplayGuard { out, active, done: false } + DisplayGuard { + out, + active, + done: false, + } } /// Emit the cleanup postlude exactly once (idempotent; no-op when inactive). @@ -931,7 +950,10 @@ fn parting_prose(end: &PumpEnd, endpoint_id: &str, remote_node: Option<&str>) -> PumpEnd::Displaced(by) => { format!("\r\n[displaced — '{endpoint_id}' was taken over by {by}]") } - PumpEnd::ReconnectGaveUp { detail, daemon_down } => { + PumpEnd::ReconnectGaveUp { + detail, + daemon_down, + } => { if *daemon_down { format!( "\r\n[session '{endpoint_id}' lost — the spt daemon is down and \ @@ -1072,16 +1094,12 @@ impl SessionProbe { /// reads as absence (the downstream surfaces own that refusal copy). // [impl->REQ-RC-HONEST-SESSION-AUTHORITY] pub(crate) fn session_truth(&mut self, endpoint_id: &str) -> SessionTruth { - match self - .brain - .sessions() - .ok() - .and_then(|reply| { - reply - .sessions - .into_iter() - .find(|s| s.endpoint == endpoint_id) - }) { + match self.brain.sessions().ok().and_then(|reply| { + reply + .sessions + .into_iter() + .find(|s| s.endpoint == endpoint_id) + }) { None => SessionTruth::Absent, Some(s) => { if spt_daemon::broker::session_is_zombie( @@ -1348,10 +1366,8 @@ fn driver_of_record(status: Option<&str>, driven_by: Option) -> OptionREQ-RC-DRIVER-READ-LIVENESS] fn current_driver(endpoint_id: &str) -> Option { - let perch = spt_store::perch::resolve_perch_path( - endpoint_id, - spt_store::perch::ParentHint::Infer, - ); + let perch = + spt_store::perch::resolve_perch_path(endpoint_id, spt_store::perch::ParentHint::Infer); spt_store::info::read_info(&perch) .and_then(|i| driver_of_record(i.status.as_deref(), i.driven_by)) } @@ -1376,7 +1392,12 @@ fn parse_stdin_chunk(armed: &mut bool, input: &[u8]) -> DetachParse { if *armed { *armed = false; match b { - DETACH_KEY => return DetachParse { forward, detach: true }, + DETACH_KEY => { + return DetachParse { + forward, + detach: true, + } + } DETACH_PREFIX => forward.push(DETACH_PREFIX), // literal ctrl-b other => { forward.push(DETACH_PREFIX); @@ -1625,7 +1646,9 @@ const CEREMONY_CHROME_ROWS: usize = 4; /// terminal, minus the chrome. The bottom half stays the session's, so the /// operator can still see what the endpoint is doing while they decide. fn ceremony_capacity(rows: u16) -> usize { - ((rows / 2) as usize).saturating_sub(CEREMONY_CHROME_ROWS).max(1) + ((rows / 2) as usize) + .saturating_sub(CEREMONY_CHROME_ROWS) + .max(1) } /// The content as DISPLAY ROWS at `cols`: newline-split, each logical line @@ -1878,8 +1901,9 @@ pub fn prompt_bringup_code(endpoint_id: &str) -> Result, String> )); }; let node = spt_store::hostlabel::node_fill_label(None); - prompt_digits(&bringup_prompt_label(node.as_deref(), &room.home_subnet)) - .map_err(|e| format!("'{endpoint_id}' asks for a bring-up code and {e} — pass --code ")) + prompt_digits(&bringup_prompt_label(node.as_deref(), &room.home_subnet)).map_err(|e| { + format!("'{endpoint_id}' asks for a bring-up code and {e} — pass --code ") + }) } /// The shared raw-mode digits prompt behind every ceremony code entry (the @@ -1935,10 +1959,7 @@ pub fn prompt_digits(label: &str) -> Result, String> { /// backstop + BrokerGone EOF still guard a session that dies after /// confirmation, so this is not a blank-hang reopening. // [impl->REQ-ENDPOINT-UNBOUND-ATTACH] -pub fn run_attach_session_confirmed( - endpoint_id: &str, - intent: AttachIntent, -) -> Result<(), String> { +pub fn run_attach_session_confirmed(endpoint_id: &str, intent: AttachIntent) -> Result<(), String> { run_attach_inner(endpoint_id, intent, true, None) } @@ -1980,7 +2001,11 @@ fn run_attach_inner( println!("{refusal}"); return Ok(()); } - let driver = if plain_target { current_driver(&bare_id) } else { None }; + let driver = if plain_target { + current_driver(&bare_id) + } else { + None + }; if pre_broker_busy_guidance(intent, plain_target, driver.as_deref()) { let node = driver.unwrap_or_default(); let own_hex = crate::roster::own_node_hex(); @@ -2085,19 +2110,17 @@ fn run_attach_inner( // satellite exists (standing ruling). // [impl->REQ-RC-HARNESS-ONLY-REFUSAL] let local_harness_only = plain_target - && spt_store::info::read_info(&perch_path).is_some_and(|i| { - harness_only_row(&i.state, i.controllable, i.status.as_deref()) - }); + && spt_store::info::read_info(&perch_path) + .is_some_and(|i| harness_only_row(&i.state, i.controllable, i.status.as_deref())); let remote_harness_only = !local_harness_only - && crate::wansend::resolve_visible_owner_instance(endpoint_id) - .is_some_and(|inst| { - inst.harness_only - && matches!( - inst.status, - spt_net::net::registry::Status::Active - | spt_net::net::registry::Status::Dormant - ) - }); + && crate::wansend::resolve_visible_owner_instance(endpoint_id).is_some_and(|inst| { + inst.harness_only + && matches!( + inst.status, + spt_net::net::registry::Status::Active + | spt_net::net::registry::Status::Dormant + ) + }); if local_harness_only || remote_harness_only { println!( "Endpoint '{endpoint_id}' is online but harness-hosted — spt does not \ @@ -2200,7 +2223,11 @@ fn run_attach_inner( // REQ-HAZARD-RC-ATTACH-FAILFAST / REQ-RC-CROSS-NODE-ATTACH surfaces // unchanged) so the teardown matrix drives postlude-precedes-prose. Ok(end) => { - let _ = writeln!(stdout, "{}", parting_prose(&end, endpoint_id, remote_node.as_deref())); + let _ = writeln!( + stdout, + "{}", + parting_prose(&end, endpoint_id, remote_node.as_deref()) + ); Ok(()) } Err(e) => Err(public_attach_failure(endpoint_id, e)), @@ -2461,9 +2488,7 @@ fn establish_attach( or any visible subnet." ))) } - crate::wansend::OwnerDial::Ambiguous(msg) => { - return Err(EstablishFail::NoTarget(msg)) - } + crate::wansend::OwnerDial::Ambiguous(msg) => return Err(EstablishFail::NoTarget(msg)), crate::wansend::OwnerDial::Unreachable { node, detail } => { return Err(EstablishFail::NoTarget(format!( "'{endpoint_id}' is on {node}, but it is not reachable ({detail})." @@ -2488,12 +2513,12 @@ fn establish_attach( // A LOCAL attach (plain-bare hit OR LocalOwner — `req_endpoint` // is None exactly then): the broker's in-process loopback // singleton (re-mint/reuse). - None if req_endpoint.is_none() => brain - .net_dial_loopback() - .map_err(|e| { - std::io::Error::other(format!("loopback re-dial: {e}")) - })? - .conn_id, + None if req_endpoint.is_none() => { + brain + .net_dial_loopback() + .map_err(|e| std::io::Error::other(format!("loopback re-dial: {e}")))? + .conn_id + } // Remote: re-resolve + re-dial the owning node. None => match crate::wansend::resolve_and_dial_owner(&mut brain, endpoint_id) { crate::wansend::OwnerDial::Dialed { conn_id, .. } => conn_id, @@ -2623,7 +2648,9 @@ fn attach_viewport( // and working, never the old apparent freeze at a static "Reconnecting…". // establish_attach is CONNECT-ONLY: a down daemon yields DaemonDown here and // is retried (the operator may bring it back) WITHOUT any WMI resurrection. - let target = remote_node.clone().unwrap_or_else(|| "local daemon".to_string()); + let target = remote_node + .clone() + .unwrap_or_else(|| "local daemon".to_string()); let retry_started = Instant::now(); let mut attempt: u64 = 0; let reestablished = loop { @@ -2684,8 +2711,7 @@ fn attach_viewport( // daemon (only knowable for a LOCAL target) gets the loud "session // lost — daemon down" copy; anything else keeps the generic // didn't-reconnect copy. Remote severs never probe local daemon state. - let daemon_down = - remote_node.is_none() && !spt_daemon::daemon::is_running(); + let daemon_down = remote_node.is_none() && !spt_daemon::daemon::is_running(); return Ok(PumpEnd::ReconnectGaveUp { detail: severed_kind.to_string(), daemon_down, @@ -2774,7 +2800,11 @@ fn reconnect_banner_bytes(rows: u16, cols: u16, target: &str, remaining_secs: u6 // Center on the CHARACTER count (the terminal cell count for this ASCII+… // line), clamped so an over-wide text still starts on-screen. let width = text.chars().count() as u16; - let col = if width >= cols { 1 } else { (cols - width) / 2 + 1 }; + let col = if width >= cols { + 1 + } else { + (cols - width) / 2 + 1 + }; let mut out = Vec::new(); out.extend_from_slice(b"\x1b[2J\x1b[H"); out.extend_from_slice(format!("\x1b[{row};{col}H").as_bytes()); @@ -2806,7 +2836,10 @@ enum PumpEnd { /// local daemon was still down at give-up (REQ-RC-RECONNECT-TRUTH) — it /// selects the loud "session lost — daemon down" copy over the generic /// didn't-reconnect copy. [impl->REQ-RC-RECONNECT] [impl->REQ-RC-RECONNECT-TRUTH] - ReconnectGaveUp { detail: String, daemon_down: bool }, + ReconnectGaveUp { + detail: String, + daemon_down: bool, + }, /// The attach produced NO event whatsoever within the generous first-event /// backstop window (REQ-HAZARD-RC-ATTACH-FAILFAST path b): a healthy session — /// even one still painting / mid-init — replays its buffered output (or at @@ -3086,9 +3119,7 @@ fn pump( } Ok(StdinMsg::Detach) => return Ok(detach(brain, stream_id)), Err(mpsc::TryRecvError::Empty) => break, - Err(mpsc::TryRecvError::Disconnected) => { - return Ok(detach(brain, stream_id)) - } + Err(mpsc::TryRecvError::Disconnected) => return Ok(detach(brain, stream_id)), } } } @@ -3114,7 +3145,11 @@ fn pump( }; seen_any = true; // any broker event proves the attach stream is live match ev { - BrokerEvent::NetStreamData { stream_id: sid, bytes, .. } if sid == stream_id => { + BrokerEvent::NetStreamData { + stream_id: sid, + bytes, + .. + } if sid == stream_id => { for rec in decoder.push(&bytes) { match rec { AttachRecord::Output { seq, data_b64 } => { @@ -3128,7 +3163,9 @@ fn pump( // Track the harness's mouse-reporting mode from its output // (REQ-RC-MOUSE-FORWARD) before rendering it verbatim. mouse_scanner.feed(mouse_mode, &bytes); - stdout.write_all(&bytes).map_err(|e| format!("write: {e}"))?; + stdout + .write_all(&bytes) + .map_err(|e| format!("write: {e}"))?; // Re-assert the reserved row if the harness output just // destroyed our scroll region — alt-screen enter or a // DECSTBM reset (REQ-RC-IDENTITY). The trigger MEANS the @@ -3217,8 +3254,7 @@ fn pump( // a refusal, never truncation. let content = decode_bytes(&content_b64) .map_err(|e| format!("decode ceremony content: {e}"))?; - let (tcols, trows) = - crossterm::terminal::size().unwrap_or((80, 24)); + let (tcols, trows) = crossterm::terminal::size().unwrap_or((80, 24)); // The FIDO2 offer, withdrawn silently unless // this node is the enrolled node (SIGNET W2). let payload = fido2_offer_stands( @@ -3377,7 +3413,10 @@ mod tests { fido2_offer_stands(Some("aa11bb22"), Some(&payload_b64), None), None ); - assert_eq!(fido2_offer_stands(Some("aa11bb22"), None, Some("aa11bb22")), None); + assert_eq!( + fido2_offer_stands(Some("aa11bb22"), None, Some("aa11bb22")), + None + ); } // [unit->REQ-SEAL-ENROLL-SHORTCUT-E] the prompt row's E hint renders @@ -3401,9 +3440,15 @@ mod tests { assert!(!plain.contains("E = enroll"), "{plain}"); assert!(!plain.contains("enrolling this node"), "{plain}"); - let offered = CeremonyOverlay { offer_enroll: true, ..base }; + let offered = CeremonyOverlay { + offer_enroll: true, + ..base + }; let painted = String::from_utf8_lossy(&offered.paint_bytes(24, 80)).into_owned(); - assert!(painted.contains("E = enroll authenticator + submit"), "{painted}"); + assert!( + painted.contains("E = enroll authenticator + submit"), + "{painted}" + ); let ensured = CeremonyOverlay { enroll_facts: Some(("aabb".to_string(), "hello-kcm-rs256".to_string())), @@ -3444,14 +3489,23 @@ mod tests { painted.contains("promote v0.60.0 to stable"), "content line 1 verbatim" ); - assert!(painted.contains("signed: the operator"), "content line 2 verbatim"); + assert!( + painted.contains("signed: the operator"), + "content line 2 verbatim" + ); assert!( painted.contains("subnet 'bignet'"), "the binding subnet is NAMED so the human reaches for the right key" ); assert!(painted.contains("code: 123"), "the typed digits echo"); - assert!(painted.contains("wrong code (1 counted)"), "the status renders"); - assert!(painted.contains("Esc cancels"), "the cancel affordance is stated"); + assert!( + painted.contains("wrong code (1 counted)"), + "the status renders" + ); + assert!( + painted.contains("Esc cancels"), + "the cancel affordance is stated" + ); // Byte-identity: the buffer the overlay paints IS the mint's buffer. assert_eq!(c.content, content); // And the paint is cursor-neutral: DECSC opens, DECRC closes. @@ -3496,10 +3550,16 @@ mod tests { // 24-row terminal: capacity = 12 - 4 chrome = 8 content rows. assert_eq!(ceremony_capacity(24), 8); // A wide line wraps: one 200-char line at 80 cols = 3 display rows. - assert_eq!(ceremony_display_rows("w".repeat(200).as_bytes(), 80).len(), 3); + assert_eq!( + ceremony_display_rows("w".repeat(200).as_bytes(), 80).len(), + 3 + ); // Twelve lines over an 8-row window: scroll 0 shows 1..=8 and names // 4 below; scroll 4 shows 5..=12. - let content = (1..=12).map(|i| format!("line-{i}")).collect::>().join("\n"); + let content = (1..=12) + .map(|i| format!("line-{i}")) + .collect::>() + .join("\n"); let mut c = CeremonyOverlay { ceremony_id: 1, content: content.clone().into_bytes(), @@ -3513,16 +3573,25 @@ mod tests { }; let top = String::from_utf8_lossy(&c.paint_bytes(24, 80)).into_owned(); assert!(top.contains("line-1") && top.contains("line-8")); - assert!(!top.contains("line-9"), "off-window rows are off-screen, not gone"); + assert!( + !top.contains("line-9"), + "off-window rows are off-screen, not gone" + ); assert!(top.contains("4 below"), "the indicator names what is below"); c.scroll = 4; let bottom = String::from_utf8_lossy(&c.paint_bytes(24, 80)).into_owned(); assert!(bottom.contains("line-12") && bottom.contains("line-5")); - assert!(!bottom.contains("line-4\x1b"), "scrolled-past rows leave the window"); + assert!( + !bottom.contains("line-4\x1b"), + "scrolled-past rows leave the window" + ); // A wild offset clamps to the last window rather than blanking. c.scroll = 999; let clamped = String::from_utf8_lossy(&c.paint_bytes(24, 80)).into_owned(); - assert!(clamped.contains("line-12"), "the clamp keeps the tail reachable"); + assert!( + clamped.contains("line-12"), + "the clamp keeps the tail reachable" + ); // Never shrinks: every display row concatenated is the content verbatim. assert_eq!( ceremony_display_rows(content.as_bytes(), 80).join("\n"), @@ -3555,7 +3624,11 @@ mod tests { fn submit_is_not_gated_on_scroll_position() { let c = CeremonyOverlay { ceremony_id: 3, - content: (1..=40).map(|i| format!("row-{i}")).collect::>().join("\n").into_bytes(), + content: (1..=40) + .map(|i| format!("row-{i}")) + .collect::>() + .join("\n") + .into_bytes(), subnet: "bignet".to_string(), destination: None, buf: "123456".to_string(), @@ -3583,8 +3656,16 @@ mod tests { // Backspace edits, non-digits are ignored. #[test] fn ceremony_keys_fold_through_the_shared_kernel() { - assert_eq!(fold_code_bytes("12", &[0x1b]), CodePromptStep::Cancel, "Esc cancels"); - assert_eq!(fold_code_bytes("12", &[0x03]), CodePromptStep::Cancel, "ctrl-c cancels"); + assert_eq!( + fold_code_bytes("12", &[0x1b]), + CodePromptStep::Cancel, + "Esc cancels" + ); + assert_eq!( + fold_code_bytes("12", &[0x03]), + CodePromptStep::Cancel, + "ctrl-c cancels" + ); assert_eq!( fold_code_bytes("12", &[0x1b, b'[', b'A']), CodePromptStep::Continue("12".to_string()), @@ -3787,18 +3868,38 @@ mod tests { fn harness_only_row_matches_online_seatless_live_agents_only() { use spt_store::liveness::STATUS_ONLINE; // The reproduced field shape: online live_agent, controllable=Some(false). - assert!(harness_only_row("live_agent", Some(false), Some(STATUS_ONLINE))); + assert!(harness_only_row( + "live_agent", + Some(false), + Some(STATUS_ONLINE) + )); // Legacy None self-corrects at next bind — until then it reads // harness-only, matching the picker's amber + the gossiped fact. assert!(harness_only_row("live_agent", None, Some(STATUS_ONLINE))); // A broker PTY seat → attachable, never this refusal. - assert!(!harness_only_row("live_agent", Some(true), Some(STATUS_ONLINE))); + assert!(!harness_only_row( + "live_agent", + Some(true), + Some(STATUS_ONLINE) + )); // Not a live_agent → not this refusal. - assert!(!harness_only_row("worker", Some(false), Some(STATUS_ONLINE))); + assert!(!harness_only_row( + "worker", + Some(false), + Some(STATUS_ONLINE) + )); // Offline/unbound/status-less harness rows fall to the truthful // offline / no-session copy instead. - assert!(!harness_only_row("live_agent", Some(false), Some("offline"))); - assert!(!harness_only_row("live_agent", Some(false), Some("unbound"))); + assert!(!harness_only_row( + "live_agent", + Some(false), + Some("offline") + )); + assert!(!harness_only_row( + "live_agent", + Some(false), + Some("unbound") + )); assert!(!harness_only_row("live_agent", Some(false), None)); } @@ -3814,16 +3915,36 @@ mod tests { fn pre_broker_busy_guidance_fires_for_any_driver_not_just_remote() { use spt_net::net::attach::AttachIntent; // Remote driver → guidance, no broker. - assert!(pre_broker_busy_guidance(AttachIntent::Control, true, Some("desktop"))); + assert!(pre_broker_busy_guidance( + AttachIntent::Control, + true, + Some("desktop") + )); // Own-node (same-machine second window) driver → SAME refusal, no bypass. - assert!(pre_broker_busy_guidance(AttachIntent::Control, true, Some("own-node-hex"))); + assert!(pre_broker_busy_guidance( + AttachIntent::Control, + true, + Some("own-node-hex") + )); // --view / --take bypass (watching coexists; taking displaces). - assert!(!pre_broker_busy_guidance(AttachIntent::Viewer, true, Some("desktop"))); - assert!(!pre_broker_busy_guidance(AttachIntent::Take, true, Some("desktop"))); + assert!(!pre_broker_busy_guidance( + AttachIntent::Viewer, + true, + Some("desktop") + )); + assert!(!pre_broker_busy_guidance( + AttachIntent::Take, + true, + Some("desktop") + )); // No driver latched → the broker's generation ladder owns the answer. assert!(!pre_broker_busy_guidance(AttachIntent::Control, true, None)); // A qualified target names the resolver's answer — never gated here. - assert!(!pre_broker_busy_guidance(AttachIntent::Control, false, Some("desktop"))); + assert!(!pre_broker_busy_guidance( + AttachIntent::Control, + false, + Some("desktop") + )); } // [unit->REQ-ER-RC-INTENT-LOCKS] the client-side half of the engine room's @@ -3847,7 +3968,11 @@ mod tests { "the local controls must keep working" ); assert!(engine_room_client_refusal(true, false, AttachIntent::Take).is_none()); - for intent in [AttachIntent::Viewer, AttachIntent::Control, AttachIntent::Take] { + for intent in [ + AttachIntent::Viewer, + AttachIntent::Control, + AttachIntent::Take, + ] { assert!( engine_room_client_refusal(false, true, intent).is_none(), "no other endpoint is touched" @@ -3919,8 +4044,14 @@ mod tests { "a record with no status field is left alone, not treated as stale" ); // No driver latched → nothing to report, whatever the status reads. - assert_eq!(driver_of_record(Some(spt_store::liveness::STATUS_OFFLINE), None), None); - assert_eq!(driver_of_record(Some(spt_store::liveness::STATUS_ONLINE), None), None); + assert_eq!( + driver_of_record(Some(spt_store::liveness::STATUS_OFFLINE), None), + None + ); + assert_eq!( + driver_of_record(Some(spt_store::liveness::STATUS_ONLINE), None), + None + ); } fn count_occurrences(hay: &[u8], needle: &[u8]) -> usize { @@ -3949,7 +4080,11 @@ mod tests { g.finish(); g.finish(); drop(g); - assert_eq!(cap.snapshot(), DISPLAY_TEARDOWN_POSTLUDE.to_vec(), "exactly one postlude"); + assert_eq!( + cap.snapshot(), + DISPLAY_TEARDOWN_POSTLUDE.to_vec(), + "exactly one postlude" + ); let piped = Capture::default(); drop(DisplayGuard::new(piped.clone(), false)); @@ -3969,8 +4104,14 @@ mod tests { PumpEnd::Exited(Some(0)), PumpEnd::Detached, PumpEnd::Displaced("node-b".to_string()), - PumpEnd::ReconnectGaveUp { detail: "connection lost".to_string(), daemon_down: true }, - PumpEnd::ReconnectGaveUp { detail: "connection lost".to_string(), daemon_down: false }, + PumpEnd::ReconnectGaveUp { + detail: "connection lost".to_string(), + daemon_down: true, + }, + PumpEnd::ReconnectGaveUp { + detail: "connection lost".to_string(), + daemon_down: false, + }, PumpEnd::Stalled, PumpEnd::NoLiveSession, ]; @@ -4040,7 +4181,10 @@ mod tests { got & ENABLE_VIRTUAL_TERMINAL_PROCESSING != 0, "VT-output processing enabled" ); - assert!(got & ENABLE_PROCESSED_OUTPUT != 0, "processed output enabled"); + assert!( + got & ENABLE_PROCESSED_OUTPUT != 0, + "processed output enabled" + ); assert!( got & ENABLE_WRAP_AT_EOL_OUTPUT != 0, "prior console bits preserved" @@ -4105,12 +4249,21 @@ mod tests { fn first_event_stall_decision() { // No event + past the generous grace → stalled. assert!(first_event_stalled(false, FIRST_EVENT_GRACE)); - assert!(first_event_stalled(false, FIRST_EVENT_GRACE + Duration::from_secs(1))); + assert!(first_event_stalled( + false, + FIRST_EVENT_GRACE + Duration::from_secs(1) + )); // Any event seen → never stalled (the working/mid-init attach guard). - assert!(!first_event_stalled(true, FIRST_EVENT_GRACE + Duration::from_secs(60))); + assert!(!first_event_stalled( + true, + FIRST_EVENT_GRACE + Duration::from_secs(60) + )); // Before the grace → not yet (a slow-painting session still has time). assert!(!first_event_stalled(false, Duration::from_secs(1))); - assert!(!first_event_stalled(false, FIRST_EVENT_GRACE - Duration::from_millis(1))); + assert!(!first_event_stalled( + false, + FIRST_EVENT_GRACE - Duration::from_millis(1) + )); } /// Shared capture sink for a headless viewport drive (the seam's `out`). @@ -4215,21 +4368,22 @@ mod tests { // Returns the OWNING brain too — the finish kills the session through it // (KIND_KILL requires the spawner's session binding). let spawn_ticker = |broker_name: &str| -> (spt_daemon::brain::Brain, u64) { - let mut host = spt_daemon::brain::Brain::cold_start(broker_name, 1) - .expect("host brain connects"); - let sid = host.spawn_session(spt_daemon::msg::SpawnReq { - program: prog.clone(), - args: args.clone(), - rows: 24, - cols: 80, - endpoint: "reheal".to_string(), - cwd: None, - env: Default::default(), - translation_binary: None, - adapter: String::new(), - install_dir: None, - }) - .expect("spawn ticker session"); + let mut host = + spt_daemon::brain::Brain::cold_start(broker_name, 1).expect("host brain connects"); + let sid = host + .spawn_session(spt_daemon::msg::SpawnReq { + program: prog.clone(), + args: args.clone(), + rows: 24, + cols: 80, + endpoint: "reheal".to_string(), + cwd: None, + env: Default::default(), + translation_binary: None, + adapter: String::new(), + install_dir: None, + }) + .expect("spawn ticker session"); (host, sid) }; @@ -4297,14 +4451,15 @@ mod tests { let cap = Capture::default(); let mut cap_out = cap.clone(); let viewport = std::thread::spawn(move || { - let est = establish_attach("reheal", AttachIntent::Viewer, None, None).map_err(|e| { - let msg = match e { - EstablishFail::NoTarget(m) => format!("establish no-target: {m}"), - EstablishFail::DaemonDown => "establish daemon-down".to_string(), - EstablishFail::Error(m) => format!("establish error: {m}"), - }; - msg - })?; + let est = + establish_attach("reheal", AttachIntent::Viewer, None, None).map_err(|e| { + let msg = match e { + EstablishFail::NoTarget(m) => format!("establish no-target: {m}"), + EstablishFail::DaemonDown => "establish daemon-down".to_string(), + EstablishFail::Error(m) => format!("establish error: {m}"), + }; + msg + })?; let mouse = MouseMode::default(); let mut remote = est.remote_node.clone(); attach_viewport( @@ -4356,11 +4511,15 @@ mod tests { let (mut host2, _sid2) = spawn_ticker(&broker_name); let banner_needle = b"Reconnecting to "; - let full = wait_for(&viewport, "the reconnect banner + post-bounce output", &|s| { - s.windows(banner_needle.len()) - .position(|w| w == banner_needle) - .is_some_and(|i| String::from_utf8_lossy(&s[i..]).contains("tick")) - }); + let full = wait_for( + &viewport, + "the reconnect banner + post-bounce output", + &|s| { + s.windows(banner_needle.len()) + .position(|w| w == banner_needle) + .is_some_and(|i| String::from_utf8_lossy(&s[i..]).contains("tick")) + }, + ); // Ordering proof: output BEFORE the banner (the live pre-bounce // viewport), the banner, then output AFTER it (the re-established one). let banner_at = full @@ -4455,7 +4614,10 @@ mod tests { #[cfg(unix)] let (prog, args) = ( "sh".to_string(), - vec!["-c".to_string(), "while true; do echo tick; sleep 0.2; done".to_string()], + vec![ + "-c".to_string(), + "while true; do echo tick; sleep 0.2; done".to_string(), + ], ); #[cfg(windows)] let (prog, args) = ( @@ -4465,8 +4627,7 @@ mod tests { "for /l %i in (0,0,1) do @(echo tick & ping -n 2 127.0.0.1 >nul)".to_string(), ], ); - let mut spawner = - spt_daemon::brain::Brain::cold_start(&name, 1).expect("spawner connects"); + let mut spawner = spt_daemon::brain::Brain::cold_start(&name, 1).expect("spawner connects"); spawner .spawn_session(spt_daemon::msg::SpawnReq { program: prog, @@ -4493,21 +4654,28 @@ mod tests { // cold-started pump can no longer dial in. broker.stop(); - let est = - establish_attach("single-pump", AttachIntent::Viewer, Some(probe.into_brain()), None) - .unwrap_or_else(|e| { - let msg = match e { - EstablishFail::NoTarget(m) => format!("no-target: {m}"), - EstablishFail::DaemonDown => "daemon-down".to_string(), - EstablishFail::Error(m) => format!("error: {m}"), - }; - panic!( - "a regressed establish_attach that ignores the carried Brain and \ + let est = establish_attach( + "single-pump", + AttachIntent::Viewer, + Some(probe.into_brain()), + None, + ) + .unwrap_or_else(|e| { + let msg = match e { + EstablishFail::NoTarget(m) => format!("no-target: {m}"), + EstablishFail::DaemonDown => "daemon-down".to_string(), + EstablishFail::Error(m) => format!("error: {m}"), + }; + panic!( + "a regressed establish_attach that ignores the carried Brain and \ cold-starts a fresh one would fail here — the broker's accept loop \ is stopped: {msg}" - ) - }); - assert_eq!(est.remote_node, None, "a local attach carries no remote node"); + ) + }); + assert_eq!( + est.remote_node, None, + "a local attach carries no remote node" + ); spawner.kill_session().expect("kill session"); dispatch_stop.store(true, std::sync::atomic::Ordering::Release); @@ -4633,7 +4801,11 @@ mod tests { reg.merge_instance("l1", instance(&own_hex)); let reg_dir = spt_store::perch::identity_dir().join("registry"); std::fs::create_dir_all(®_dir).unwrap(); - std::fs::write(reg_dir.join("s1.json"), serde_json::to_string(®).unwrap()).unwrap(); + std::fs::write( + reg_dir.join("s1.json"), + serde_json::to_string(®).unwrap(), + ) + .unwrap(); { use spt_store::peeraddrs::{peer_addrs_file, PeerAddrStore}; PeerAddrStore::record(&peer_addrs_file(), &b_hex, b_addr).unwrap(); @@ -4644,7 +4816,10 @@ mod tests { #[cfg(unix)] let (prog, args) = ( "sh".to_string(), - vec!["-c".to_string(), "while true; do echo tick; sleep 0.2; done".to_string()], + vec![ + "-c".to_string(), + "while true; do echo tick; sleep 0.2; done".to_string(), + ], ); #[cfg(windows)] let (prog, args) = ( @@ -4677,23 +4852,25 @@ mod tests { let cases: [(&str, String, bool); 4] = [ ("q1", "s1:q1".to_string(), true), ("q2", format!("q2@{b_prefix}"), true), - ("q3", "q3".to_string(), true), // bare → local miss → cross-node + ("q3", "q3".to_string(), true), // bare → local miss → cross-node ("l1", "s1:l1".to_string(), false), // LocalOwner: qualified-local attach ]; for (endpoint, target, expect_remote) in cases { - let owner = if expect_remote { &remote_name } else { &local_name }; + let owner = if expect_remote { + &remote_name + } else { + &local_name + }; let mut host = spawn_ticker(owner, endpoint); let cap = Capture::default(); let mut cap_out = cap.clone(); let target_for_thread = target.clone(); let viewport = std::thread::spawn(move || { - let est = - establish_attach(&target_for_thread, AttachIntent::Viewer, None, None).map_err(|e| { - match e { - EstablishFail::NoTarget(m) => format!("no-target: {m}"), - EstablishFail::DaemonDown => "daemon-down".to_string(), - EstablishFail::Error(m) => format!("error: {m}"), - } + let est = establish_attach(&target_for_thread, AttachIntent::Viewer, None, None) + .map_err(|e| match e { + EstablishFail::NoTarget(m) => format!("no-target: {m}"), + EstablishFail::DaemonDown => "daemon-down".to_string(), + EstablishFail::Error(m) => format!("error: {m}"), })?; let remote = est.remote_node.clone(); let mouse = MouseMode::default(); @@ -4811,7 +4988,9 @@ mod tests { #[test] fn reconnect_window_expiry_decision() { assert!(!reconnect_expired(Duration::from_secs(0))); - assert!(!reconnect_expired(RECONNECT_WINDOW - Duration::from_millis(1))); + assert!(!reconnect_expired( + RECONNECT_WINDOW - Duration::from_millis(1) + )); assert!(reconnect_expired(RECONNECT_WINDOW)); assert!(reconnect_expired(RECONNECT_WINDOW + Duration::from_secs(1))); } @@ -4830,7 +5009,10 @@ mod tests { // Over-wide text: col clamps to 1 (never a subtraction underflow). let narrow = reconnect_banner_bytes(2, 10, "a-very-long-node-name-indeed", 5); let ns = String::from_utf8_lossy(&narrow); - assert!(ns.contains("\x1b[1;1H"), "clamped to col 1 row 1, got {ns:?}"); + assert!( + ns.contains("\x1b[1;1H"), + "clamped to col 1 row 1, got {ns:?}" + ); } // [unit->REQ-RC-RECONNECT-TRUTH] the banner carries a VISIBLE countdown — the @@ -4908,8 +5090,14 @@ mod tests { } }; let down = render("the daemon connection dropped", true); - assert!(down.contains("daemon is down"), "names the daemon-down truth"); - assert!(down.contains("won't auto-start"), "states rc won't resurrect it"); + assert!( + down.contains("daemon is down"), + "names the daemon-down truth" + ); + assert!( + down.contains("won't auto-start"), + "states rc won't resurrect it" + ); // The PRIMARY spelling (releases#112). NOTE, and it is a real weakness of // this test rather than a nicety: the closure above is a PARALLEL SPELLING // of the production copy, not a call into it, so this assertion pins the @@ -4920,8 +5108,14 @@ mod tests { // this string, since that one reads the REAL binary's stderr. assert!(down.contains("spt node start"), "points at the restart"); let generic = render("the connection was severed", false); - assert!(!generic.contains("won't auto-start"), "generic omits the daemon-down line"); - assert!(generic.contains("didn't succeed"), "keeps the didn't-reconnect copy"); + assert!( + !generic.contains("won't auto-start"), + "generic omits the daemon-down line" + ); + assert!( + generic.contains("didn't succeed"), + "keeps the didn't-reconnect copy" + ); } // [int->REQ-RC-RECONNECT-TRUTH] rc is CONNECT-ONLY: an attach against a STOPPED @@ -4961,7 +5155,10 @@ mod tests { std::thread::sleep(Duration::from_millis(20)); } let outcome = worker.join().expect("attach worker joins"); - assert!(outcome.is_ok(), "a loud clean exit, not an Err: {outcome:?}"); + assert!( + outcome.is_ok(), + "a loud clean exit, not an Err: {outcome:?}" + ); // The WMI-resurrection RED: the attach birthed NO daemon. assert!( !spt_daemon::daemon::is_running(), @@ -5000,11 +5197,20 @@ mod tests { fn classify_read_err_eof_is_graceful_not_fatal() { use std::io::ErrorKind::*; // The exact kind behind "failed to fill whole buffer". - assert_eq!(classify_read_err(UnexpectedEof), ReadDisposition::BrokerGone); + assert_eq!( + classify_read_err(UnexpectedEof), + ReadDisposition::BrokerGone + ); // Same severed-stream class. assert_eq!(classify_read_err(BrokenPipe), ReadDisposition::BrokerGone); - assert_eq!(classify_read_err(ConnectionReset), ReadDisposition::BrokerGone); - assert_eq!(classify_read_err(ConnectionAborted), ReadDisposition::BrokerGone); + assert_eq!( + classify_read_err(ConnectionReset), + ReadDisposition::BrokerGone + ); + assert_eq!( + classify_read_err(ConnectionAborted), + ReadDisposition::BrokerGone + ); // Poll-slice timeouts retry (no event this slice). assert_eq!(classify_read_err(WouldBlock), ReadDisposition::Retry); assert_eq!(classify_read_err(TimedOut), ReadDisposition::Retry); @@ -5049,7 +5255,10 @@ mod tests { fn detach_prefix_spans_chunks() { let mut armed = false; // chunk 1 ends on the bare prefix: nothing forwarded yet, armed carries. - assert_eq!(parse(&mut armed, &[b'a', DETACH_PREFIX]), (b"a".to_vec(), false)); + assert_eq!( + parse(&mut armed, &[b'a', DETACH_PREFIX]), + (b"a".to_vec(), false) + ); assert!(armed, "prefix armed across the chunk boundary"); // chunk 2 starts with the detach key: detach fires. assert_eq!(parse(&mut armed, &[DETACH_KEY]), (Vec::new(), true)); @@ -5107,7 +5316,7 @@ mod tests { // Backspace / Ctrl+Backspace — relocated W7 evidence: // [unit->REQ-HAZARD-RC-INPUT-KEY-ENCODING] assert_eq!(ev(KeyCode::Backspace, N), vec![0x7f]); // char-delete DEL - // [unit->REQ-HAZARD-RC-INPUT-KEY-ENCODING] + // [unit->REQ-HAZARD-RC-INPUT-KEY-ENCODING] assert_eq!(ev(KeyCode::Backspace, ctrl), vec![0x08]); // word-delete ^H // --- CSI tilde keys (unmodified) --- @@ -5216,7 +5425,10 @@ mod tests { CodePromptStep::Submit("482913".to_string()) ); // Esc and ctrl-c cancel, content or not. - assert_eq!(fold_code_key("4829", &ke(KeyCode::Esc)), CodePromptStep::Cancel); + assert_eq!( + fold_code_key("4829", &ke(KeyCode::Esc)), + CodePromptStep::Cancel + ); assert_eq!(fold_code_key("", &ke(KeyCode::Esc)), CodePromptStep::Cancel); assert_eq!( fold_code_key( @@ -5238,12 +5450,18 @@ mod tests { fn bringup_prompt_names_the_node_and_the_home_subnet() { let line = bringup_prompt_label(Some("HFENDULEAM"), "bignet"); assert!(line.contains("HFENDULEAM"), "the node is named: {line}"); - assert!(line.contains("bignet"), "the anchor subnet is named: {line}"); + assert!( + line.contains("bignet"), + "the anchor subnet is named: {line}" + ); assert!( line.contains("member or admin"), "both keys stay acceptable: {line}" ); - assert!(line.contains("Esc cancels"), "the cancel key is stated: {line}"); + assert!( + line.contains("Esc cancels"), + "the cancel key is stated: {line}" + ); // A node label the OS declined to supply drops the phrase rather than // rendering an empty one — the SUBNET is the fact the human needs, and @@ -5282,7 +5500,10 @@ mod tests { let mut armed = false; match key_event_step(&mut armed, ke(KeyCode::Char('b'), ctrl)) { KeyAction::Swallow => {} - other => panic!("unarmed Ctrl+B should Swallow, got {:?}", action_name(&other)), + other => panic!( + "unarmed Ctrl+B should Swallow, got {:?}", + action_name(&other) + ), } assert!(armed, "Ctrl+B must arm the SM"); @@ -5297,7 +5518,10 @@ mod tests { armed = true; match key_event_step(&mut armed, ke(KeyCode::Char('b'), ctrl)) { KeyAction::Forward(v) => assert_eq!(v, vec![0x02]), - other => panic!("armed + Ctrl+B should Forward [0x02], got {:?}", action_name(&other)), + other => panic!( + "armed + Ctrl+B should Forward [0x02], got {:?}", + action_name(&other) + ), } assert!(!armed); @@ -5305,7 +5529,10 @@ mod tests { armed = true; match key_event_step(&mut armed, ke(KeyCode::Char('x'), none)) { KeyAction::Forward(v) => assert_eq!(v, vec![0x02, b'x']), - other => panic!("armed + 'x' should Forward [0x02,'x'], got {:?}", action_name(&other)), + other => panic!( + "armed + 'x' should Forward [0x02,'x'], got {:?}", + action_name(&other) + ), } assert!(!armed); @@ -5317,7 +5544,10 @@ mod tests { vec![0x02, 0x04], "Ctrl+D must forward prefix + ^D, never detach" ), - other => panic!("armed + Ctrl+D must NOT Detach, got {:?}", action_name(&other)), + other => panic!( + "armed + Ctrl+D must NOT Detach, got {:?}", + action_name(&other) + ), } assert!(!armed); @@ -5325,7 +5555,10 @@ mod tests { armed = false; match key_event_step(&mut armed, ke(KeyCode::Char('a'), none)) { KeyAction::Forward(v) => assert_eq!(v, vec![b'a']), - other => panic!("unarmed 'a' should Forward ['a'], got {:?}", action_name(&other)), + other => panic!( + "unarmed 'a' should Forward ['a'], got {:?}", + action_name(&other) + ), } assert!(!armed); } @@ -5348,7 +5581,10 @@ mod tests { #[test] fn bracketed_paste_framing_is_exact_and_content_verbatim() { // Single line. - assert_eq!(wrap_bracketed_paste(b"hi"), b"\x1b[200~hi\x1b[201~".to_vec()); + assert_eq!( + wrap_bracketed_paste(b"hi"), + b"\x1b[200~hi\x1b[201~".to_vec() + ); // Multi-line: newlines stay literal INSIDE the markers (no \r submit-storm, // no per-char translation), markers exactly once around the whole block. let content = b"line1\nline2\nline3"; @@ -5373,12 +5609,20 @@ mod tests { row: 0, modifiers: KeyModifiers::NONE, }; - assert!(mouse_is_paste(&me(MouseEventKind::Down(MouseButton::Right)))); + assert!(mouse_is_paste(&me(MouseEventKind::Down( + MouseButton::Right + )))); assert!(!mouse_is_paste(&me(MouseEventKind::Up(MouseButton::Right)))); - assert!(!mouse_is_paste(&me(MouseEventKind::Down(MouseButton::Left)))); - assert!(!mouse_is_paste(&me(MouseEventKind::Down(MouseButton::Middle)))); + assert!(!mouse_is_paste(&me(MouseEventKind::Down( + MouseButton::Left + )))); + assert!(!mouse_is_paste(&me(MouseEventKind::Down( + MouseButton::Middle + )))); assert!(!mouse_is_paste(&me(MouseEventKind::Moved))); - assert!(!mouse_is_paste(&me(MouseEventKind::Drag(MouseButton::Right)))); + assert!(!mouse_is_paste(&me(MouseEventKind::Drag( + MouseButton::Right + )))); assert!(!mouse_is_paste(&me(MouseEventKind::ScrollDown))); } @@ -5413,7 +5657,10 @@ mod tests { }; assert_eq!(scroll_dir(&me(MouseEventKind::ScrollUp)), Some(true)); assert_eq!(scroll_dir(&me(MouseEventKind::ScrollDown)), Some(false)); - assert_eq!(scroll_dir(&me(MouseEventKind::Down(MouseButton::Right))), None); + assert_eq!( + scroll_dir(&me(MouseEventKind::Down(MouseButton::Right))), + None + ); assert_eq!(scroll_dir(&me(MouseEventKind::Moved)), None); assert_eq!(scroll_dir(&me(MouseEventKind::ScrollLeft)), None); } @@ -5468,7 +5715,10 @@ mod tests { let mut sc = MouseModeScanner::default(); // `ESC[?1006h` split right in the middle of the digits. sc.feed(&mode, b"tail\x1b[?100"); - assert!(!mode.sgr.load(Acquire), "incomplete half must not toggle yet"); + assert!( + !mode.sgr.load(Acquire), + "incomplete half must not toggle yet" + ); sc.feed(&mode, b"6hmore"); assert!(mode.sgr.load(Acquire), "the completed sequence toggles sgr"); // Split at the very ESC/[/? boundary too. @@ -5485,7 +5735,10 @@ mod tests { // assert here trips as a reminder to re-verify the sticky-overlay behavior. #[test] fn status_row_marker_is_disabled_by_flag() { - assert!(!status_row_active(false), "controller: id marker is OFF (#14)"); + assert!( + !status_row_active(false), + "controller: id marker is OFF (#14)" + ); assert!(!status_row_active(true), "a viewer never owns a status row"); } @@ -5499,12 +5752,18 @@ mod tests { "ops : doyle @ HFENDULEAM" ); // local (unset anchor subnet) still renders the subnet slot. - assert_eq!(identity_line("local", "perri", Some("box")), "local : perri @ box"); + assert_eq!( + identity_line("local", "perri", Some("box")), + "local : perri @ box" + ); // No node → tail omitted. assert_eq!(identity_line("local", "perri", None), "local : perri"); // Empty / whitespace node → tail omitted (trimmed, never a bare ` @ `). assert_eq!(identity_line("local", "perri", Some("")), "local : perri"); - assert_eq!(identity_line("local", "perri", Some(" ")), "local : perri"); + assert_eq!( + identity_line("local", "perri", Some(" ")), + "local : perri" + ); } // [unit->REQ-RC-IDENTITY] the DECSTBM margin assert reserves row 1 EXACTLY: @@ -5513,7 +5772,11 @@ mod tests { // bottom) fail. #[test] fn status_assert_reserves_row1_then_repaints() { - let s = StatusRow { text: "x".to_string(), rows: 24, cols: 80 }; + let s = StatusRow { + text: "x".to_string(), + rows: 24, + cols: 80, + }; let bytes = s.assert_bytes(); // The margin set comes first. assert!( @@ -5531,7 +5794,11 @@ mod tests { #[test] fn status_repaint_exact_bytes_and_right_align() { // Short text, right-aligned: width 5 in 80 cols → start col 76. - let s = StatusRow { text: "abcde".to_string(), rows: 24, cols: 80 }; + let s = StatusRow { + text: "abcde".to_string(), + rows: 24, + cols: 80, + }; let mut expect = Vec::new(); expect.extend_from_slice(b"\x1b7"); // DECSC expect.extend_from_slice(b"\x1b[1;1H"); // home @@ -5544,11 +5811,19 @@ mod tests { assert_eq!(s.repaint_bytes(), expect); // Exact fit: width == cols → col 1. - let s = StatusRow { text: "abcd".to_string(), rows: 10, cols: 4 }; + let s = StatusRow { + text: "abcd".to_string(), + rows: 10, + cols: 4, + }; assert!(s.repaint_bytes().windows(6).any(|w| w == b"\x1b[1;1H")); // Text WIDER than cols → clamp to col 1 (never col 0 / negative). - let s = StatusRow { text: "wide banner text".to_string(), rows: 10, cols: 4 }; + let s = StatusRow { + text: "wide banner text".to_string(), + rows: 10, + cols: 4, + }; let bytes = s.repaint_bytes(); assert!( bytes.windows(6).any(|w| w == b"\x1b[1;1H"), @@ -5556,23 +5831,30 @@ mod tests { String::from_utf8_lossy(&bytes) ); // The text still rides verbatim. - assert!( - bytes.windows(b"wide banner text".len()).any(|w| w == b"wide banner text") - ); + assert!(bytes + .windows(b"wide banner text".len()) + .any(|w| w == b"wide banner text")); } // [unit->REQ-RC-IDENTITY] restore tears the reserved row down: reset the scroll // region to full screen (`ESC[r`) then clear the reclaimed row 1 — EXACT bytes. #[test] fn status_restore_exact_bytes() { - assert_eq!(StatusRow::restore_bytes(), b"\x1b[r\x1b[1;1H\x1b[2K".to_vec()); + assert_eq!( + StatusRow::restore_bytes(), + b"\x1b[r\x1b[1;1H\x1b[2K".to_vec() + ); } // [unit->REQ-RC-IDENTITY] update_size re-points the tracked terminal size (the // banner repaints on the NEW geometry after a window change). #[test] fn status_update_size_repoints_geometry() { - let mut s = StatusRow { text: "id".to_string(), rows: 24, cols: 80 }; + let mut s = StatusRow { + text: "id".to_string(), + rows: 24, + cols: 80, + }; s.update_size(40, 120); assert_eq!((s.rows, s.cols), (40, 120)); // The repaint now right-aligns against 120 cols: 120 - 2 + 1 = 119. @@ -5616,7 +5898,10 @@ mod tests { fn reassert_scanner_survives_split_across_chunks() { // `ESC[?1049h` split mid-digits. let mut sc = ReassertScanner::default(); - assert!(!sc.feed(b"tail\x1b[?10"), "incomplete half must not fire yet"); + assert!( + !sc.feed(b"tail\x1b[?10"), + "incomplete half must not fire yet" + ); assert!(sc.feed(b"49hmore"), "the completed alt-screen enter fires"); // `ESC[r` split at the ESC/[ boundary. let mut sc = ReassertScanner::default(); @@ -5651,7 +5936,8 @@ mod tests { let assert_len = sink.len(); assert!(sink.starts_with(b"\x1b[2;24r"), "start reserves the row"); assert!( - sink.windows(b"local : doyle @ BOX".len()).any(|w| w == b"local : doyle @ BOX"), + sink.windows(b"local : doyle @ BOX".len()) + .any(|w| w == b"local : doyle @ BOX"), "the identity banner is painted at start" ); @@ -5660,7 +5946,11 @@ mod tests { if scanner.feed(plain) { sink.write_all(&status.assert_bytes()).unwrap(); } - assert_eq!(sink.len(), assert_len, "plain output emits no status re-assert"); + assert_eq!( + sink.len(), + assert_len, + "plain output emits no status re-assert" + ); // (b') harness output WITH an alt-screen enter → re-assert (MARGIN + paint). // The trigger destroyed the scroll region, so the pump re-sets the margin, @@ -5673,7 +5963,10 @@ mod tests { sink.write_all(&status.assert_bytes()).unwrap(); } assert!(fired, "the alt-screen enter trips the re-assert scanner"); - assert!(sink.len() > before, "a re-assert was appended after the trigger"); + assert!( + sink.len() > before, + "a re-assert was appended after the trigger" + ); assert!( sink[before..].starts_with(b"\x1b[2;24r"), "the re-assert re-sets the DECSTBM margin (not just a repaint)" diff --git a/crates/spt/src/roster.rs b/crates/spt/src/roster.rs index f1d72713..200ab467 100644 --- a/crates/spt/src/roster.rs +++ b/crates/spt/src/roster.rs @@ -32,7 +32,9 @@ pub(crate) fn is_own_node_hex(driver: &str, own_hex: Option<&str>) -> bool { /// The single resolution point the own-node display humanizations key on. // [impl->REQ-DRIVEN-BY-OWN-NODE-NORMALIZE] pub(crate) fn own_node_hex() -> Option { - spt_store::nodeid::load_or_create().ok().map(|k| k.public_key().to_hex()) + spt_store::nodeid::load_or_create() + .ok() + .map(|k| k.public_key().to_hex()) } /// A snapshot of one perch for `spt list`. @@ -382,8 +384,16 @@ mod tests { bind(&owlery.join("me"), "me", "live_agent"); // One conventionally named child, one named nothing like its parent. - bind(&owlery.join("me").join("nested").join("me-w1"), "me-w1", "worker"); - bind(&owlery.join("me").join("nested").join("zeta"), "zeta", "worker"); + bind( + &owlery.join("me").join("nested").join("me-w1"), + "me-w1", + "worker", + ); + bind( + &owlery.join("me").join("nested").join("zeta"), + "zeta", + "worker", + ); // A psyche COMPANION: custody record, no info.json — the shape every // psyche in the field actually has. let psyche = owlery.join("me").join("nested").join("me-psyche"); @@ -473,7 +483,10 @@ mod tests { #[test] fn match_self_by_ancestry_disambiguates_and_none() { let ancestry = [4321u32, 999, 1]; - let two_live = [("hall-a".to_string(), 4321u32), ("hall-b".to_string(), 5555)]; + let two_live = [ + ("hall-a".to_string(), 4321u32), + ("hall-b".to_string(), 5555), + ]; assert_eq!( match_self_by_ancestry(&ancestry, &two_live).as_deref(), Some("hall-a"), @@ -491,7 +504,10 @@ mod tests { // candidates' read_dir order. ancestry = [inner_parent, outer_grandparent]. let nested_ancestry = [200u32, 100]; // candidates listed OUTER-first (worst case for a candidate-order scan). - let both = [("psyche-host".to_string(), 100u32), ("agent".to_string(), 200)]; + let both = [ + ("psyche-host".to_string(), 100u32), + ("agent".to_string(), 200), + ]; assert_eq!( match_self_by_ancestry(&nested_ancestry, &both).as_deref(), Some("agent"), @@ -565,7 +581,10 @@ mod tests { line.contains("--from"), "and the reader is told what the sender WILL be labelled instead: {line}" ); - assert!(line.ends_with('\n'), "one composed line, newline included: {line}"); + assert!( + line.ends_with('\n'), + "one composed line, newline included: {line}" + ); assert!( !line.trim_end().contains(" "), "no interior space run — an eaten continuation renders mid-sentence: {line}" @@ -579,7 +598,10 @@ mod tests { #[test] fn one_perch_matching_on_both_its_pids_still_resolves() { let ancestry = [4321u32, 999, 1]; - let same_perch_twice = [("hall-bf".to_string(), 4321u32), ("hall-bf".to_string(), 4321)]; + let same_perch_twice = [ + ("hall-bf".to_string(), 4321u32), + ("hall-bf".to_string(), 4321), + ]; assert_eq!( match_self_by_ancestry(&ancestry, &same_perch_twice).as_deref(), Some("hall-bf"), @@ -595,7 +617,10 @@ mod tests { #[test] fn ambiguity_is_scoped_to_the_nearest_ancestor() { let nested = [200u32, 100]; - let clean_inner = [("psyche-host".to_string(), 100u32), ("agent".to_string(), 200)]; + let clean_inner = [ + ("psyche-host".to_string(), 100u32), + ("agent".to_string(), 200), + ]; assert_eq!( match_self_by_ancestry(&nested, &clean_inner).as_deref(), Some("agent"), @@ -716,7 +741,9 @@ mod tests { // Both the top-level Self perch AND the nested psyche perch are enumerated. let resolve = |session: &str| { dirs.iter().find_map(|d| { - info::read_info(d).filter(|r| r.session_id == session).map(|r| r.id) + info::read_info(d) + .filter(|r| r.session_id == session) + .map(|r| r.id) }) }; assert_eq!( diff --git a/crates/spt/src/sealverb.rs b/crates/spt/src/sealverb.rs index fcdf02d7..8efeaba4 100644 --- a/crates/spt/src/sealverb.rs +++ b/crates/spt/src/sealverb.rs @@ -220,7 +220,9 @@ pub(crate) fn cmd_seal_mint( } }; let Some(minter) = minter.or_else(crate::roster::detect_self_id) else { - spt_proto::emit_line_err!("NO_SELF: seal mint needs a minter endpoint (--minter or $OWL_SESSION_ID)"); + spt_proto::emit_line_err!( + "NO_SELF: seal mint needs a minter endpoint (--minter or $OWL_SESSION_ID)" + ); return 1; }; let regs = crate::wansend::load_snapshots(&perch::identity_dir().join("registry")); @@ -249,7 +251,9 @@ pub(crate) fn cmd_seal_mint( let mut brain = match Brain::cold_start(&spt_daemon::broker_socket_name(), now_ms()) { Ok(b) => b, Err(e) => { - spt_proto::emit_line_err!("SEAL_MINT_NO_DAEMON: cannot reach the daemon ({e}) — nothing was minted"); + spt_proto::emit_line_err!( + "SEAL_MINT_NO_DAEMON: cannot reach the daemon ({e}) — nothing was minted" + ); if from_shortform { record_shortform_outcome(&minter, false, "SEAL_MINT_NO_DAEMON"); } @@ -360,7 +364,8 @@ pub(crate) fn cmd_seal_enroll(endpoint: Option, subnet: Option) "SEAL_ENROLL_ALREADY_ENROLLED: node {node} x subnet '{binding}' already \ holds pubkey {} ({}); records are immutable in v1 — re-enrollment or \ revocation needs an operator ruling.", - held.pubkey_hex, held.backend_kind + held.pubkey_hex, + held.backend_kind ); return 1; } @@ -452,8 +457,10 @@ pub(crate) fn run_seal_ceremony_for_dispatch( if let Err(e) = spt_daemon::ensure_running() { spt_proto::emit_line_err!("DAEMON_START_WARN: {e}"); } - let mut brain = Brain::cold_start(&spt_daemon::broker_socket_name(), now_ms()) - .map_err(|e| format!("SEAL_SEND_NO_DAEMON: cannot reach the daemon ({e}) — nothing was sent"))?; + let mut brain = + Brain::cold_start(&spt_daemon::broker_socket_name(), now_ms()).map_err(|e| { + format!("SEAL_SEND_NO_DAEMON: cannot reach the daemon ({e}) — nothing was sent") + })?; let reply = brain .seal_ceremony(minter, &binding, body.as_bytes(), Some(&dest_id)) .map_err(|e| e.to_string())?; @@ -461,7 +468,9 @@ pub(crate) fn run_seal_ceremony_for_dispatch( (0, token, _) => Ok(token), // The daemon's own sentence rides verbatim; this leg only adds what // became of the message, which is the half the sender needs. - (_, _, detail) => Err(format!("{detail}\nSEAL_SEND_NOT_SENT:{target}: not delivered (nothing was spooled)")), + (_, _, detail) => Err(format!( + "{detail}\nSEAL_SEND_NOT_SENT:{target}: not delivered (nothing was spooled)" + )), } } @@ -527,14 +536,19 @@ mod tests { // Override outside the minter's membership: named refusal. assert_eq!( resolve_binding_subnet(Some("elsewhere"), Some("home"), &minter, None), - Err(SealBindRefusal::OverrideNotMinterMember("elsewhere".to_string())) + Err(SealBindRefusal::OverrideNotMinterMember( + "elsewhere".to_string() + )) ); // No shared subnet: named refusal, never a fallback. - let refusal = - resolve_binding_subnet(None, Some("home"), &minter, Some(&set(&["theirs"]))) - .unwrap_err(); + let refusal = resolve_binding_subnet(None, Some("home"), &minter, Some(&set(&["theirs"]))) + .unwrap_err(); assert_eq!(refusal, SealBindRefusal::NoSharedSubnet); - assert!(refusal.render().starts_with("SEAL_NO_SHARED_SUBNET:"), "{}", refusal.render()); + assert!( + refusal.render().starts_with("SEAL_NO_SHARED_SUBNET:"), + "{}", + refusal.render() + ); } // [unit->REQ-SEAL-SUBNET-BINDING-DEFAULT] the shared-set pick is a set @@ -560,7 +574,7 @@ mod tests { // a Windows `echo |` pipes is stripped, interior whitespace is untouched, // and empty-after-trim refuses by name BEFORE any ceremony could open. #[test] - fn mint_content_trims_like_send_and_refuses_empty() { + fn mint_content_trims_like_send_and_refuses_empty() { assert_eq!(mint_content("ship it\r\n"), Ok("ship it")); assert_eq!(mint_content(" two words \n"), Ok("two words")); let refusal = mint_content(" \r\n ").unwrap_err(); @@ -575,8 +589,7 @@ mod tests { // delivering or spooling. #[test] fn sealed_dispatch_refusals_send_nothing_by_name() { - let err = run_seal_ceremony_for_dispatch("doyle", Some("todlando"), None, "") - .unwrap_err(); + let err = run_seal_ceremony_for_dispatch("doyle", Some("todlando"), None, "").unwrap_err(); assert!(err.starts_with("SEAL_SEND_NO_CONTENT:"), "{err}"); assert!(err.contains("nothing was sent"), "{err}"); @@ -622,15 +635,17 @@ mod tests { // detail verbatim on stderr, a detail-less one naming its outcome. #[test] fn enroll_outcome_exit_zero_iff_admitted_and_details_ride_verbatim() { - let record_lines = - "SEAL_ENROLLED\npubkey_hex: abcd\nnode: aa11bb22\nsubnet: home\n\ + let record_lines = "SEAL_ENROLLED\npubkey_hex: abcd\nnode: aa11bb22\nsubnet: home\n\ enrolled_at: 42\nbackend_kind: hello-kcm-rs256"; assert_eq!( enroll_outcome(&reply("admitted", record_lines, None)), (0, record_lines.to_string(), String::new()) ); for (outcome, detail) in [ - ("refused", "SEAL_ENROLL_ALREADY_ENROLLED: node aa11bb22 x subnet 'home'..."), + ( + "refused", + "SEAL_ENROLL_ALREADY_ENROLLED: node aa11bb22 x subnet 'home'...", + ), ("throttled", "the seal gate is shut — retry in 8s"), ("cancelled", "the human cancelled at the overlay"), ] { diff --git a/crates/spt/src/teardown.rs b/crates/spt/src/teardown.rs index 150e7b0c..741fcffc 100644 --- a/crates/spt/src/teardown.rs +++ b/crates/spt/src/teardown.rs @@ -222,7 +222,10 @@ pub(crate) fn teardown_hosted_session(id: &str, bound: Duration) -> TeardownResu }; let root_pid = session.pid; let mut brain = probe.into_brain(); - if brain.teardown_session(Some(session.session_id), id).is_err() { + if brain + .teardown_session(Some(session.session_id), id) + .is_err() + { // The request never left; nothing was torn down. return unconfirmed_verdict(root_pid, root_provably_gone); } @@ -318,7 +321,10 @@ mod tests { #[test] fn timeout_refuses_the_stamp_and_names_the_survivor() { assert!( - !TeardownResult::TimedOut { root_pid: Some(4242) }.may_stamp(), + !TeardownResult::TimedOut { + root_pid: Some(4242) + } + .may_stamp(), "a survivor must never be stamped over" ); for ok in [ @@ -332,13 +338,19 @@ mod tests { let line = timeout_line("STOP", "doyle", Some(4242)); assert!(line.contains("STOP_FAIL:doyle"), "stable token: {line}"); - assert!(line.contains("4242"), "names the surviving root pid: {line}"); + assert!( + line.contains("4242"), + "names the surviving root pid: {line}" + ); assert!( line.contains("NOT stamped"), "states that nothing was stamped: {line}" ); #[cfg(windows)] - assert!(line.contains("taskkill /PID 4242"), "names the remedy: {line}"); + assert!( + line.contains("taskkill /PID 4242"), + "names the remedy: {line}" + ); #[cfg(not(windows))] assert!(line.contains("kill -9"), "names the remedy: {line}"); diff --git a/crates/spt/src/trustwarnverb.rs b/crates/spt/src/trustwarnverb.rs index f4f58a7b..e46c46b2 100644 --- a/crates/spt/src/trustwarnverb.rs +++ b/crates/spt/src/trustwarnverb.rs @@ -73,10 +73,7 @@ pub enum TrustWarnOutcome { /// The whole decision: writes need positively-confirmed elevation, reads never /// do. // [impl->REQ-TRUST-WARNING-OVERRIDE] -pub fn classify_trust_warning_verb( - verb: TrustWarnVerb, - elevation: Elevation, -) -> TrustWarnOutcome { +pub fn classify_trust_warning_verb(verb: TrustWarnVerb, elevation: Elevation) -> TrustWarnOutcome { if !verb.writes() { return TrustWarnOutcome::Proceed; } @@ -155,7 +152,11 @@ mod tests { fn the_gate_keys_on_whether_the_verb_writes() { assert!(!TrustWarnVerb::Show.writes()); assert!(TrustWarnVerb::Set.writes() && TrustWarnVerb::Reset.writes()); - for verb in [TrustWarnVerb::Show, TrustWarnVerb::Set, TrustWarnVerb::Reset] { + for verb in [ + TrustWarnVerb::Show, + TrustWarnVerb::Set, + TrustWarnVerb::Reset, + ] { let refused = classify_trust_warning_verb(verb, Elevation::NotElevated) == TrustWarnOutcome::RefuseUnelevated; assert_eq!(refused, verb.writes(), "{verb:?} gated iff it writes"); diff --git a/crates/spt/src/unlisted.rs b/crates/spt/src/unlisted.rs index a87dd85a..cba7d319 100644 --- a/crates/spt/src/unlisted.rs +++ b/crates/spt/src/unlisted.rs @@ -106,7 +106,10 @@ pub fn rows_from( } } _ => { - let node = best.get(&e.id).and_then(|k| k.node.clone()).or(e.node.clone()); + let node = best + .get(&e.id) + .and_then(|k| k.node.clone()) + .or(e.node.clone()); best.insert(e.id.clone(), Evidence { node, ..e }); } } @@ -205,9 +208,7 @@ pub fn evidence_from_knocks(store: &spt_store::knock::KnockStore) -> Vec { - "we knocked them; no answer has reached this node".to_string() - } + (Some(_), _, _) => "we knocked them; no answer has reached this node".to_string(), // Same-node: the receipt exists, so this is a real answer. (None, Some(_), _) => "we knocked them; they approved".to_string(), (None, None, KnockState::Denied) => "we knocked them; they declined".to_string(), @@ -438,7 +439,10 @@ mod tests { let from_rules = evidence_from_rules(&store); assert_eq!(from_rules.len(), 1, "{from_rules:?}"); assert_eq!(from_rules[0].id, "far-peer"); - assert_eq!(from_rules[0].node, None, "a rule names an endpoint, not a node"); + assert_eq!( + from_rules[0].node, None, + "a rule names an endpoint, not a node" + ); assert_eq!(from_rules[0].provenance, Provenance::AdmitsInbound); let mut ledger = ContactLedger::default(); @@ -467,7 +471,11 @@ mod tests { .into_iter() .map(|e| e.id) .collect(); - assert_eq!(ids, vec!["recent".to_string()], "the aged row is not evidence"); + assert_eq!( + ids, + vec!["recent".to_string()], + "the aged row is not evidence" + ); } // [unit->REQ-UNLISTED-RENDER] the evidence phrase never contains a liveness @@ -565,7 +573,11 @@ mod tests { "the same-node row HAS the receipt, so it may say so: {near:?}" ); - assert_eq!(far.node.as_deref(), Some("node-b"), "the cross-node row carries where we sent it"); + assert_eq!( + far.node.as_deref(), + Some("node-b"), + "the cross-node row carries where we sent it" + ); assert_eq!(near.node, None, "a same-node row has no other node to name"); assert_eq!(far.provenance, Provenance::InvitedOutbound); assert_eq!(near.provenance, Provenance::InvitedOutbound); @@ -605,7 +617,9 @@ mod tests { fn a_receipt_proven_cross_node_knock_renders_its_answer() { use spt_store::knock::PreAuthKey; let mut store = knock_store(vec![knock_row("far-peer", Some("node-b"), None)]); - store.pre_auths.push(pre_auth(PreAuthKey::Knock, "k-far-peer", true)); + store + .pre_auths + .push(pre_auth(PreAuthKey::Knock, "k-far-peer", true)); let rows = evidence_from_knocks(&store); let far = rows.iter().find(|r| r.id == "far-peer").expect("{rows:?}"); @@ -641,8 +655,14 @@ mod tests { fn no_cross_node_silence_is_ever_read_as_an_answer() { use spt_store::knock::PreAuthKey; for (label, arm) in [ - ("armed but not consumed", Some(pre_auth(PreAuthKey::Knock, "k-far-peer", false))), - ("never armed (non-mutual), or DENIED and therefore removed", None), + ( + "armed but not consumed", + Some(pre_auth(PreAuthKey::Knock, "k-far-peer", false)), + ), + ( + "never armed (non-mutual), or DENIED and therefore removed", + None, + ), ( "a CODE redemption sharing the id — a different keyspace", Some(pre_auth(PreAuthKey::Code, "k-far-peer", true)), @@ -684,11 +704,21 @@ mod tests { inbound.knocker_node = "node-b".to_string(); let only_inbound = evidence_from_knocks(&knock_store(vec![inbound.clone()])); - assert!(only_inbound.is_empty(), "a knock we received is not invited-outbound: {only_inbound:?}"); + assert!( + only_inbound.is_empty(), + "a knock we received is not invited-outbound: {only_inbound:?}" + ); - let both = evidence_from_knocks(&knock_store(vec![inbound, knock_row("far-peer", Some("node-b"), None)])); + let both = evidence_from_knocks(&knock_store(vec![ + inbound, + knock_row("far-peer", Some("node-b"), None), + ])); let ids: Vec<&str> = both.iter().map(|r| r.id.as_str()).collect(); - assert_eq!(ids, vec!["far-peer"], "and the knock we SENT still produces its row"); + assert_eq!( + ids, + vec!["far-peer"], + "and the knock we SENT still produces its row" + ); } // [unit->REQ-UNLISTED-EVIDENCE] no knock evidence phrase claims liveness, @@ -710,7 +740,11 @@ mod tests { assert_eq!(rows.len(), 4, "{rows:?}"); let phrases: BTreeSet<&str> = rows.iter().map(|r| r.detail.as_str()).collect(); - assert_eq!(phrases.len(), 4, "each shape says its own thing: {phrases:?}"); + assert_eq!( + phrases.len(), + 4, + "each shape says its own thing: {phrases:?}" + ); for row in &rows { for word in ["online", "offline", "listening", "busy", "reachable"] { diff --git a/crates/spt/src/wansend.rs b/crates/spt/src/wansend.rs index 4c119f8b..36b5fc41 100644 --- a/crates/spt/src/wansend.rs +++ b/crates/spt/src/wansend.rs @@ -22,7 +22,7 @@ use std::path::Path; use std::time::Duration; use spt_daemon::brain::Brain; -use spt_daemon::effect::{Minter, MintedOp}; +use spt_daemon::effect::{MintedOp, Minter}; use spt_daemon::endpoint::broker_socket_name; use spt_net::net::endpoint::addr_for_node_hex; use spt_net::net::presencemsg::Presence; @@ -285,7 +285,9 @@ pub fn resolve_and_dial_owner(brain: &mut Brain, endpoint: &str) -> OwnerDial { let instance = match resolve_across_visible(®s, &address, &own_hex, excluded) { Resolution::Resolved { instance, .. } => instance, - Resolution::Ambiguous(a) => return OwnerDial::Ambiguous(render_refusal(&address.id, &a, ®s)), + Resolution::Ambiguous(a) => { + return OwnerDial::Ambiguous(render_refusal(&address.id, &a, ®s)) + } Resolution::NotFound => return OwnerDial::NotFound, }; if instance.node == own_hex { @@ -326,7 +328,10 @@ pub fn resolve_and_dial_owner(brain: &mut Brain, endpoint: &str) -> OwnerDial { /// rc can refuse truthfully BEFORE any attach/stream. // [impl->REQ-RC-HARNESS-ONLY-REFUSAL] pub fn resolve_visible_owner_instance(endpoint: &str) -> Option { - let own_hex = spt_store::nodeid::load_or_create().ok()?.public_key().to_hex(); + let own_hex = spt_store::nodeid::load_or_create() + .ok()? + .public_key() + .to_hex(); let address = Address::parse(endpoint).ok()?; let regs = load_snapshots(&perch::identity_dir().join("registry")); let excl = Exclusions::load(); @@ -1595,16 +1600,16 @@ pub fn redeem_route(code: &str) -> RedeemRoute { .map(|(subnet, sealed)| (subnet.to_string(), sealed.node_short_hex())) .collect(); - let (winner, node) = match select_routed_opening(&pairs, |subnet, short| match regs.get(subnet) - { - Some(reg) => resolve_short_node(reg, short), - // A subnet with no registry snapshot resolves nothing — the same - // outcome as a snapshot that simply does not hold the short key. - None => ShortNodeRoute::Unresolved, - }) { - Ok(picked) => picked, - Err(refusal) => return refusal, - }; + let (winner, node) = + match select_routed_opening(&pairs, |subnet, short| match regs.get(subnet) { + Some(reg) => resolve_short_node(reg, short), + // A subnet with no registry snapshot resolves nothing — the same + // outcome as a snapshot that simply does not hold the short key. + None => ShortNodeRoute::Unresolved, + }) { + Ok(picked) => picked, + Err(refusal) => return refusal, + }; let secret_hex = openings[winner].1.secret_hex(); let own_hex = match spt_store::nodeid::load_or_create() { @@ -1612,9 +1617,7 @@ pub fn redeem_route(code: &str) -> RedeemRoute { Err(e) => return RedeemRoute::Failed(format!("node identity: {e}")), }; if node == own_hex { - return RedeemRoute::Local { - secret: secret_hex, - }; + return RedeemRoute::Local { secret: secret_hex }; } RedeemRoute::Remote { node, @@ -1661,7 +1664,6 @@ pub fn redeem_send_routed( } } - /// What sending an answer receipt did, in the approver's vocabulary. /// /// **None of it can fail the approval.** The grant was decided, written and @@ -2061,9 +2063,16 @@ mod tests { // The caller's candidate-gather over the snapshot map. let cands: Vec<(String, S)> = regs .values() - .flat_map(|reg| reg.instances("ling").iter().map(|i| (i.node.clone(), i.status))) + .flat_map(|reg| { + reg.instances("ling") + .iter() + .map(|i| (i.node.clone(), i.status)) + }) .collect(); - let wake = RestGoal { target: S::Active, kind: GoalKind::Exists }; + let wake = RestGoal { + target: S::Active, + kind: GoalKind::Exists, + }; // RED before A-3: a bare id was never resolved here → local miss → WOKE_FAIL. // GREEN: exactly one actionable remote instance → route to it. assert_eq!( @@ -2087,7 +2096,10 @@ mod tests { let n = || "b-node".to_string(); assert!(matches!( classify_wan_reply(O::Delivered, n()), - WanSendOutcome::Sent { how: "delivered", .. } + WanSendOutcome::Sent { + how: "delivered", + .. + } )); assert!(matches!( classify_wan_reply(O::Spooled, n()), @@ -2095,7 +2107,10 @@ mod tests { )); assert!(matches!( classify_wan_reply(O::Duplicate, n()), - WanSendOutcome::Sent { how: "duplicate", .. } + WanSendOutcome::Sent { + how: "duplicate", + .. + } )); assert!(matches!( classify_wan_reply(O::Refused, n()), @@ -2355,7 +2370,16 @@ mod tests { // An own-node hit is NotFound (the local report stands; no self-dial). let own = reg_with("s1", target, &a_hex); let out = wan_send_with( - &mut a, &own, &a_hex, target, "doyle", None, None, "x", "op-own", |_| None, + &mut a, + &own, + &a_hex, + target, + "doyle", + None, + None, + "x", + "op-own", + |_| None, ); assert!(matches!(out, WanSendOutcome::NotFound), "got {out:?}"); @@ -2408,11 +2432,14 @@ mod tests { // dispatcher shares this home and writes its own INBOUND row for the // same hop on its own thread — a count here would race it. assert!( - spt_store::contacts::ContactLedger::load().rows.iter().any(|r| { - r.direction == spt_store::contacts::ContactDirection::Outbound - && r.endpoint == target - && r.node == b_hex - }), + spt_store::contacts::ContactLedger::load() + .rows + .iter() + .any(|r| { + r.direction == spt_store::contacts::ContactDirection::Outbound + && r.endpoint == target + && r.node == b_hex + }), "the confirmed hop records outbound contact with {target} at B" ); let mut spooled = false; diff --git a/crates/spt/tests/access_positional_allow_e2e.rs b/crates/spt/tests/access_positional_allow_e2e.rs index 331c03e3..75abb36f 100644 --- a/crates/spt/tests/access_positional_allow_e2e.rs +++ b/crates/spt/tests/access_positional_allow_e2e.rs @@ -118,7 +118,15 @@ fn the_positional_allow_honors_its_surfaces_and_still_answers_to_the_acknowledgm // the comparison is the test. // // ── ARM 1: the issue — a typed surface list on the positional spelling ── - let typed = as_user(&["endpoint", "access", "allow", "narrow", &node, "--surfaces", "MSG"]); + let typed = as_user(&[ + "endpoint", + "access", + "allow", + "narrow", + &node, + "--surfaces", + "MSG", + ]); let typed_surfaces = persisted_surfaces("narrow"); // ── ARM 2: DISCRIMINATOR — no list typed, so the empty list must persist ── diff --git a/crates/spt/tests/access_precise_allow_e2e.rs b/crates/spt/tests/access_precise_allow_e2e.rs index 1a373adb..2af16b48 100644 --- a/crates/spt/tests/access_precise_allow_e2e.rs +++ b/crates/spt/tests/access_precise_allow_e2e.rs @@ -118,7 +118,14 @@ fn the_precise_allow_leaves_the_posture_alone_and_says_when_its_rule_changes_not // // ── ARM 1: the contract — a precise grant onto an unrestricted endpoint ── let precise = as_user(&[ - "endpoint", "access", "allow", "open-ep", "--node", &node_b, "--surfaces", "MSG", + "endpoint", + "access", + "allow", + "open-ep", + "--node", + &node_b, + "--surfaces", + "MSG", ]); let precise_said = said(&precise); let precise_posture = persisted_posture("open-ep"); @@ -135,13 +142,27 @@ fn the_precise_allow_leaves_the_posture_alone_and_says_when_its_rule_changes_not // condition would get exactly backwards. let closed = as_user(&["endpoint", "access", "allow", "punch-ep", &node_a]); let punch = as_user(&[ - "endpoint", "access", "allow", "punch-ep", "--node", &node_b, "--surfaces", "MSG", + "endpoint", + "access", + "allow", + "punch-ep", + "--node", + &node_b, + "--surfaces", + "MSG", ]); let punch_said = said(&punch); // ── ARM 4: THE NAMED ABSENCE — a subject with no origin to ask about ── let stranger = as_user(&[ - "endpoint", "access", "allow", "absent-ep", "--endpoint", "stranger", "--surfaces", "MSG", + "endpoint", + "access", + "allow", + "absent-ep", + "--endpoint", + "stranger", + "--surfaces", + "MSG", ]); let stranger_said = said(&stranger); @@ -151,13 +172,7 @@ fn the_precise_allow_leaves_the_posture_alone_and_says_when_its_rule_changes_not // endpoint with no posture, so it is inert by the same reading arm 1 fires // on: if the notice were placed at the seam instead of in this arm, THIS is // where it would leak. - let mint = as_minter(&[ - "knock", - "new-code", - "--surfaces", - "MSG", - "--admit-node", - ]); + let mint = as_minter(&["knock", "new-code", "--surfaces", "MSG", "--admit-node"]); let mint_said = said(&mint); let code = mint_said .lines() @@ -188,7 +203,10 @@ fn the_precise_allow_leaves_the_posture_alone_and_says_when_its_rule_changes_not ); // ══ ASSERTIONS ══════════════════════════════════════════════════════════ - assert!(precise.status.success(), "a precise grant is a legal command"); + assert!( + precise.status.success(), + "a precise grant is a legal command" + ); assert_eq!( precise_posture, Some((None, 0)), @@ -223,7 +241,10 @@ fn the_precise_allow_leaves_the_posture_alone_and_says_when_its_rule_changes_not changes a verdict, and must not be reported as inert: {punch_said}" ); - assert!(stranger.status.success(), "the rule is legitimate and lands"); + assert!( + stranger.status.success(), + "the rule is legitimate and lands" + ); assert!( stranger_said.contains("ACCESS_GRANT_UNEVALUATED:absent-ep"), "a subject with no origin to ask about gets a NAMED ABSENCE: {stranger_said}" diff --git a/crates/spt/tests/active_only_never_relay_e2e.rs b/crates/spt/tests/active_only_never_relay_e2e.rs index db799998..fc58bf0d 100644 --- a/crates/spt/tests/active_only_never_relay_e2e.rs +++ b/crates/spt/tests/active_only_never_relay_e2e.rs @@ -32,7 +32,12 @@ use spt_store::perch; static E2E_LOCK: Mutex<()> = Mutex::new(()); /// `spt send ` with `body` on stdin, bounded off-thread so a hang fails loud. -fn send_bounded(spt_bin: &std::path::Path, home: &std::path::Path, args: &[&str], body: &str) -> Output { +fn send_bounded( + spt_bin: &std::path::Path, + home: &std::path::Path, + args: &[&str], + body: &str, +) -> Output { let mut child = Command::new(spt_bin) .no_window() .args(args) @@ -61,7 +66,9 @@ fn send_bounded(spt_bin: &std::path::Path, home: &std::path::Path, args: &[&str] /// `default` send resolves it to the WAN leg (there is no local perch). fn seed_remote_only(subnet: &str, id: &str) { let mut store = spt_store::subnet::SubnetStore::load(); - store.create_subnet(subnet, spt_store::access::Mode::Open).expect("seed subnet"); + store + .create_subnet(subnet, spt_store::access::Mode::Open) + .expect("seed subnet"); store.save().expect("save subnets"); let dir = perch::identity_dir().join("registry"); @@ -109,7 +116,12 @@ fn cross_node_active_only_stays_local_only_never_wan() { seed_remote_only("s1", "remotegw"); // ── active_only: must refuse LOCAL-ONLY, never attempt WAN. ── - let ao = send_bounded(&spt_bin, home.path(), &["send", "--active-only", "remotegw"], "background ctx"); + let ao = send_bounded( + &spt_bin, + home.path(), + &["send", "--active-only", "remotegw"], + "background ctx", + ); let ao_err = String::from_utf8_lossy(&ao.stderr); let ao_out = String::from_utf8_lossy(&ao.stdout); assert!( @@ -121,7 +133,11 @@ fn cross_node_active_only_stays_local_only_never_wan() { !ao_out.contains("SENT(WAN)") && !ao_err.contains("SENT(WAN)"), "active_only must NEVER be sent over the WAN.\nstdout=\n{ao_out}\nstderr=\n{ao_err}" ); - assert_ne!(ao.status.code(), Some(0), "the local-only refusal is a non-zero exit"); + assert_ne!( + ao.status.code(), + Some(0), + "the local-only refusal is a non-zero exit" + ); // ── default contrast: the SAME target DOES take the WAN leg (proving the guard // is active_only-specific). It fails the dial (no broker) but reached WAN. ── diff --git a/crates/spt/tests/activity_link_push_e2e.rs b/crates/spt/tests/activity_link_push_e2e.rs index 414b0de9..a2af4fb9 100644 --- a/crates/spt/tests/activity_link_push_e2e.rs +++ b/crates/spt/tests/activity_link_push_e2e.rs @@ -185,8 +185,10 @@ fn activity_frames_reach_a_linked_shell_through_the_real_daemon() { .stderr(Stdio::from(brain_log_file)) .spawn() .expect("spawn spt daemon run"); - let brain_pid = match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(120)) - { + let brain_pid = match wait_for_ready_pid( + &home.path().join("brain.ready"), + Duration::from_secs(120), + ) { Some(p) => p, None => { let _ = broker.kill(); @@ -211,7 +213,16 @@ fn activity_frames_reach_a_linked_shell_through_the_real_daemon() { let shell_perch = perch::resolve_shell_perch_path_in(&owlery, owner, shell_id); let token_of = || spt_daemon::shellhost::read_link_token(&shell_perch).expect("a link token is parked"); - let bind = |token: &str| spt(&["api", "--adapter", "mock-shell", "bind-shell", "--link", token]); + let bind = |token: &str| { + spt(&[ + "api", + "--adapter", + "mock-shell", + "bind-shell", + "--link", + token, + ]) + }; let poll = |token: &str| { spt(&[ "api", @@ -267,7 +278,13 @@ fn activity_frames_reach_a_linked_shell_through_the_real_daemon() { let body = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { // ── spawn: the noop binary exits, the perch stays offline, a token parks. let out = spt(&[ - "shell", "spawn", "mock-shell", "--alias", "Scout", "--owner", owner, + "shell", + "spawn", + "mock-shell", + "--alias", + "Scout", + "--owner", + owner, ]); assert!( out.status.success(), @@ -373,7 +390,12 @@ fn activity_frames_reach_a_linked_shell_through_the_real_daemon() { "the drive frame prints FIRST, intact: {:?}", both.lines ); - assert_eq!(both.drive.len(), 1, "exactly one drive frame: {:?}", both.lines); + assert_eq!( + both.drive.len(), + 1, + "exactly one drive frame: {:?}", + both.lines + ); assert!( both.lines[1].contains("type=\"activity\""), "the activity frame prints second, on its own line: {:?}", @@ -467,7 +489,10 @@ fn activity_frames_reach_a_linked_shell_through_the_real_daemon() { std::thread::sleep(Duration::from_millis(800)); let after = split_drain(&poll(&token_b).stdout); assert!( - after.activity.iter().all(|e| e.attr("state") == Some("busy")), + after + .activity + .iter() + .all(|e| e.attr("state") == Some("busy")), "REQ-ACTIVITY-LINK-PUSH: a frame stamped under the RETIRED link generation is \ never served to the relinked consumer — replaying the stale idle transition \ (since={stale_before}, superseded at {stale_after}) would be actively wrong: {:?}", @@ -523,10 +548,7 @@ fn activity_frames_reach_a_linked_shell_through_the_real_daemon() { observed_daemon, ); if let Err(e) = body { - eprintln!( - "{}", - common::daemon_stderr_panel(&brain_log) - ); + eprintln!("{}", common::daemon_stderr_panel(&brain_log)); std::panic::resume_unwind(e); } } diff --git a/crates/spt/tests/adapter_post_step.rs b/crates/spt/tests/adapter_post_step.rs index 44fa57db..8e1e7fca 100644 --- a/crates/spt/tests/adapter_post_step.rs +++ b/crates/spt/tests/adapter_post_step.rs @@ -20,8 +20,6 @@ use common::CommandNoWindowExt; use spt_store::perch; - - fn run_update(spt_bin: &Path, home: &Path, mode: &str, seam_out: &Path) -> std::process::Output { Command::new(spt_bin) .no_window() @@ -71,7 +69,10 @@ fn adapter_update_runs_post_step_unconditionally_and_arbitrates_notice() { let out = run_update(&spt_bin, home.path(), "custom", &seam_out); let stdout = String::from_utf8_lossy(&out.stdout); let stderr = String::from_utf8_lossy(&out.stderr); - assert!(out.status.success(), "custom mode exits 0: stderr=\n{stderr}"); + assert!( + out.status.success(), + "custom mode exits 0: stderr=\n{stderr}" + ); assert!( stdout.contains("Plugin synced — run /reload-plugins"), "custom post-step notice is printed: stdout=\n{stdout}" @@ -90,9 +91,15 @@ fn adapter_update_runs_post_step_unconditionally_and_arbitrates_notice() { assert!(seam.contains("\"adapter_applied\":false"), "seam: {seam}"); assert!(seam.contains("\"adapter_name\":\"cc\""), "seam: {seam}"); assert!(seam.contains("\"version\":\"1.0.0\""), "seam: {seam}"); - assert!(seam.contains("\"previous_version\":\"1.0.0\""), "seam: {seam}"); + assert!( + seam.contains("\"previous_version\":\"1.0.0\""), + "seam: {seam}" + ); assert!(seam.contains("\"profile_name\":null"), "seam: {seam}"); - assert!(seam.contains("\"adapter_dir\":"), "seam carries adapter_dir: {seam}"); + assert!( + seam.contains("\"adapter_dir\":"), + "seam carries adapter_dir: {seam}" + ); // ── sentinel: the reserved token fires the static [update].message. ── let _ = std::fs::remove_file(&seam_out); diff --git a/crates/spt/tests/attach_link_push_e2e.rs b/crates/spt/tests/attach_link_push_e2e.rs index 263f440a..35274db1 100644 --- a/crates/spt/tests/attach_link_push_e2e.rs +++ b/crates/spt/tests/attach_link_push_e2e.rs @@ -249,7 +249,16 @@ fn attachment_frames_reach_a_linked_shell_through_the_real_daemon() { let shell_perch = perch::resolve_shell_perch_path_in(&owlery, owner, shell_id); let token_of = || spt_daemon::shellhost::read_link_token(&shell_perch).expect("a link token is parked"); - let bind = |token: &str| spt(&["api", "--adapter", "mock-shell", "bind-shell", "--link", token]); + let bind = |token: &str| { + spt(&[ + "api", + "--adapter", + "mock-shell", + "bind-shell", + "--link", + token, + ]) + }; let poll = |token: &str| { spt(&[ "api", @@ -305,7 +314,13 @@ fn attachment_frames_reach_a_linked_shell_through_the_real_daemon() { // ── The SHELL link. ── let spawned = spt(&[ - "shell", "spawn", "mock-shell", "--alias", "Scout", "--owner", owner, + "shell", + "spawn", + "mock-shell", + "--alias", + "Scout", + "--owner", + owner, ]); assert!( spawned.status.success(), @@ -527,12 +542,15 @@ fn attachment_frames_reach_a_linked_shell_through_the_real_daemon() { if let Some(v) = viewer.as_mut() { kill_child(v); } - let psyche_perch = perch::resolve_perch_path( - &format!("{owner}-psyche"), - ParentHint::Explicit(owner), - ); + let psyche_perch = + perch::resolve_perch_path(&format!("{owner}-psyche"), ParentHint::Explicit(owner)); if let Some(p) = spt_store::info::read_pid(&psyche_perch) { - reap::authenticated_kill("attach_link_push/psyche", p, &spt_bin, reap::observe("attach_link_push/psyche", p)); + reap::authenticated_kill( + "attach_link_push/psyche", + p, + &spt_bin, + reap::observe("attach_link_push/psyche", p), + ); } let stop = { let mut cmd = Command::new(&spt_bin); diff --git a/crates/spt/tests/attach_wedge_e2e.rs b/crates/spt/tests/attach_wedge_e2e.rs index 90e418f0..bb452a28 100644 --- a/crates/spt/tests/attach_wedge_e2e.rs +++ b/crates/spt/tests/attach_wedge_e2e.rs @@ -45,8 +45,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - fn ready_pid(path: &Path) -> Option { let s = std::fs::read_to_string(path).ok()?; serde_json::from_str::(&s) @@ -67,8 +65,6 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - /// Mint the endpoint, then start its first session (the U3 two-verb bringup) /// against the registered dummyharness adapter; returns the START's captured /// output and the broker-spawned harness pid (parsed from the terse @@ -204,18 +200,18 @@ fn attach_wedge_dead_child_plus_dropped_pump_does_not_wedge_the_broker() { .stderr(Stdio::from(brain_log_file)) .spawn() .expect("spawn spt daemon run (broker process)"); - let brain_pid = match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(30)) - { - Some(p) => p, - None => { - let _ = broker.kill(); - let _ = broker.wait(); - panic!( - "PRECONDITION: brain never came up.\n{}", - common::daemon_stderr_panel(&brain_log) - ); - } - }; + let brain_pid = + match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(30)) { + Some(p) => p, + None => { + let _ = broker.kill(); + let _ = broker.wait(); + panic!( + "PRECONDITION: brain never came up.\n{}", + common::daemon_stderr_panel(&brain_log) + ); + } + }; // ── (4) Bring up the VICTIM endpoint and prove it is SERVED (rc sees the tick). ── let victim = "wedge1"; @@ -252,7 +248,9 @@ fn attach_wedge_dead_child_plus_dropped_pump_does_not_wedge_the_broker() { // `--force`: `wedge2` is a live hosted session by design, so the W3 // STOP-LIVE-SESSION-WARN contract refuses a plain stop — this teardown // intends to kill it. [int->REQ-DAEMON-STOP-LIVE-SESSION-WARN] - cmd.no_window().args(["daemon", "stop", "--force"]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["daemon", "stop", "--force"]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; @@ -285,7 +283,10 @@ fn attach_wedge_dead_child_plus_dropped_pump_does_not_wedge_the_broker() { let _ = broker.wait(); // ── Assertions. ── - assert!(victim_online, "PRECONDITION: the victim endpoint must come ONLINE"); + assert!( + victim_online, + "PRECONDITION: the victim endpoint must come ONLINE" + ); assert!( victim_served, "PRECONDITION: the victim must be SERVED (rc saw its tick) before we wedge it" diff --git a/crates/spt/tests/bind_adapter_profile_persist_e2e.rs b/crates/spt/tests/bind_adapter_profile_persist_e2e.rs index e3f46174..f0b04e5d 100644 --- a/crates/spt/tests/bind_adapter_profile_persist_e2e.rs +++ b/crates/spt/tests/bind_adapter_profile_persist_e2e.rs @@ -50,8 +50,6 @@ fn start_inproc_daemon() { panic!("in-process seed daemon did not come up"); } - - /// Create a top-level LIVE_AGENT perch pinned to `session_id` with a pre-stamped /// composite `adapter` — the "created with `:`" starting state. /// Owner pid = THIS process (alive): a re-bind under the SAME session id is a @@ -154,6 +152,12 @@ fn bind_over_created_profile_endpoint_preserves_the_profile() { out.status.success(), "the re-bind must succeed (same-session reconnect):\n{bind_err}" ); + // [int->REQ-ER-RESERVED-ID-SPAWN-REFUSAL] no engine room exists in this home; + // an ordinary bind must not query it or print unrelated refusal diagnostics. + assert!( + !bind_err.contains("ER_HOSTED_PROBE:"), + "an ordinary bind must not emit an engine-room probe diagnostic:\n{bind_err}" + ); // The load-bearing claim: the bare-parent bind did NOT clobber the profile — // info.json.adapter still reads the full composite (the A-4 regression fix). // [int->REQ-HAZARD-ADAPTER-PROFILE-STAMP-CLOBBER] diff --git a/crates/spt/tests/bind_cwd_project_e2e.rs b/crates/spt/tests/bind_cwd_project_e2e.rs index 2db6b0d6..c326eed5 100644 --- a/crates/spt/tests/bind_cwd_project_e2e.rs +++ b/crates/spt/tests/bind_cwd_project_e2e.rs @@ -40,8 +40,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - fn ready_pid(path: &Path) -> Option { let s = std::fs::read_to_string(path).ok()?; serde_json::from_str::(&s) @@ -62,8 +60,6 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - /// Mirror of the picker's `local_rows` membership derivation (data.rs:135-140): /// origin project = `project_id_for_dir(cwd)`, unioned (deduped) into the /// committed-context history. A fresh endpoint has empty history, so its @@ -212,14 +208,15 @@ fn endpoint_run_records_cwd_and_appears_under_its_project() { if let Some(p) = harness_pid { kill_pid(p); } - let psyche_perch = - perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); + let psyche_perch = perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); if let Some(p) = spt_store::info::read_pid(&psyche_perch) { kill_pid(p); } let _ = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -241,7 +238,10 @@ fn endpoint_run_records_cwd_and_appears_under_its_project() { "REQ-HAZARD-BIND-CWD-UNSET: a real endpoint-run perch must record info.cwd \ (it was NEVER set pre-W3 — the refuted v0.12.1 P1)", ); - assert!(!cwd.trim().is_empty(), "recorded cwd must be non-empty, got {cwd:?}"); + assert!( + !cwd.trim().is_empty(), + "recorded cwd must be non-empty, got {cwd:?}" + ); // The picker membership gate: the cwd-derived project id is non-empty and a // FRESH endpoint (no committed context) appears under that project SOLELY diff --git a/crates/spt/tests/bind_honest_cross_perch_e2e.rs b/crates/spt/tests/bind_honest_cross_perch_e2e.rs index 808b554b..03386008 100644 --- a/crates/spt/tests/bind_honest_cross_perch_e2e.rs +++ b/crates/spt/tests/bind_honest_cross_perch_e2e.rs @@ -45,8 +45,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - fn ready_pid(path: &Path) -> Option { let s = std::fs::read_to_string(path).ok()?; serde_json::from_str::(&s) @@ -71,7 +69,11 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { fn seed_perch(id: &str, session_id: &str, pid: u32, state: &str) -> PathBuf { let path = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&path).unwrap(); - info::write_info(&path, &InfoJson::new(id, "2026-06-01T00:00:00Z", pid, session_id, state)).unwrap(); + info::write_info( + &path, + &InfoJson::new(id, "2026-06-01T00:00:00Z", pid, session_id, state), + ) + .unwrap(); path } @@ -114,18 +116,18 @@ fn cross_perch_dead_owner_repin_is_refused_no_contamination() { .stderr(Stdio::from(brain_log_file)) .spawn() .expect("spawn spt daemon run (broker process)"); - let brain_pid = match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(30)) - { - Some(p) => p, - None => { - let _ = broker.kill(); - let _ = broker.wait(); - panic!( - "PRECONDITION: brain never came up.\n{}", - common::daemon_stderr_panel(&brain_log) - ); - } - }; + let brain_pid = + match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(30)) { + Some(p) => p, + None => { + let _ = broker.kill(); + let _ = broker.wait(); + panic!( + "PRECONDITION: brain never came up.\n{}", + common::daemon_stderr_panel(&brain_log) + ); + } + }; // Precondition: the victim is pinned to its OWN sid before the attack. assert_eq!( diff --git a/crates/spt/tests/boundary_events_e2e.rs b/crates/spt/tests/boundary_events_e2e.rs index af8cf378..75e8eeee 100644 --- a/crates/spt/tests/boundary_events_e2e.rs +++ b/crates/spt/tests/boundary_events_e2e.rs @@ -101,7 +101,8 @@ fn poll(spt_bin: &Path, home: &Path, id: &str, sid: &str, extra: &[&str]) -> ser String::from_utf8_lossy(&out.stderr) ); let text = String::from_utf8_lossy(&out.stdout).to_string(); - serde_json::from_str(&text).unwrap_or_else(|e| panic!("poll output is not JSON ({e}): {text:?}")) + serde_json::from_str(&text) + .unwrap_or_else(|e| panic!("poll output is not JSON ({e}): {text:?}")) } fn kinds(v: &serde_json::Value) -> Vec { @@ -132,18 +133,33 @@ fn boundaries_reach_the_poll_as_ordered_edges_and_are_not_replayed_to_a_seed() { let perch_path = perch::resolve_perch_path(author, ParentHint::Infer); std::fs::create_dir_all(&perch_path).unwrap(); - let rec = spt_store::info::InfoJson::new(author, "0", std::process::id(), first_sid, "live_agent"); + let rec = + spt_store::info::InfoJson::new(author, "0", std::process::id(), first_sid, "live_agent"); spt_store::info::write_info(&perch_path, &rec).unwrap(); let body = std::panic::catch_unwind(|| { // ── (1) Two DIFFERENT edges, through the real binary. - let out = boundary(&spt_bin, home.path(), author, "clear", first_sid, "boundary-sid-1"); + let out = boundary( + &spt_bin, + home.path(), + author, + "clear", + first_sid, + "boundary-sid-1", + ); assert!( out.status.success(), "a clear boundary succeeds: {}", String::from_utf8_lossy(&out.stderr) ); - let out = boundary(&spt_bin, home.path(), author, "compact", "boundary-sid-1", "boundary-sid-2"); + let out = boundary( + &spt_bin, + home.path(), + author, + "compact", + "boundary-sid-1", + "boundary-sid-2", + ); assert!( out.status.success(), "a compact boundary succeeds: {}", @@ -154,7 +170,14 @@ fn boundaries_reach_the_poll_as_ordered_edges_and_are_not_replayed_to_a_seed() { // re-report is not an error — and it must add nothing, because it // crossed no edge. Asserted before the read below so its row, if the // gate ever regresses, lands inside the window being counted. - let out = boundary(&spt_bin, home.path(), author, "compact", "boundary-sid-2", "boundary-sid-2"); + let out = boundary( + &spt_bin, + home.path(), + author, + "compact", + "boundary-sid-2", + "boundary-sid-2", + ); assert!( out.status.success(), "a re-report of the current session is still a success: {}", @@ -163,7 +186,14 @@ fn boundaries_reach_the_poll_as_ordered_edges_and_are_not_replayed_to_a_seed() { // ── (4) The closed list is enforced at the surface an adapter drives, // so the library-side coercion arm is unreachable from the CLI. - let out = boundary(&spt_bin, home.path(), author, "wharrgarbl", "boundary-sid-2", "boundary-sid-3"); + let out = boundary( + &spt_bin, + home.path(), + author, + "wharrgarbl", + "boundary-sid-2", + "boundary-sid-3", + ); assert!( !out.status.success(), "a mode outside the closed list is REFUSED, never coerced onto the wire" @@ -179,7 +209,10 @@ fn boundaries_reach_the_poll_as_ordered_edges_and_are_not_replayed_to_a_seed() { // live consumer and served from a cursor, but it is NOT replayed to // a consumer whose cursor starts now. let fresh = poll(&spt_bin, home.path(), author, "boundary-sid-2", &[]); - assert_eq!(fresh["seeded"], true, "a session with no cursor SEEDS: {fresh}"); + assert_eq!( + fresh["seeded"], true, + "a session with no cursor SEEDS: {fresh}" + ); assert_eq!( kinds(&fresh).len(), 0, @@ -195,7 +228,13 @@ fn boundaries_reach_the_poll_as_ordered_edges_and_are_not_replayed_to_a_seed() { // ── (6) …and the explicit cursor returns exactly those rows: two edges, // in order, each with its own ruled variant — and (2) empty payloads. - let history = poll(&spt_bin, home.path(), author, "boundary-sid-2", &["--after", "0"]); + let history = poll( + &spt_bin, + home.path(), + author, + "boundary-sid-2", + &["--after", "0"], + ); assert_eq!( kinds(&history), vec!["clear".to_string(), "compact".to_string()], diff --git a/crates/spt/tests/boundary_ready_strand_e2e.rs b/crates/spt/tests/boundary_ready_strand_e2e.rs index 92d69db1..28c538d0 100644 --- a/crates/spt/tests/boundary_ready_strand_e2e.rs +++ b/crates/spt/tests/boundary_ready_strand_e2e.rs @@ -39,8 +39,6 @@ fn start_inproc_daemon() { panic!("in-process seed daemon did not come up"); } - - /// Seed a fully BOUND spt-hosted perch: online + controllable + ready marker + /// live owner pid (this process) — an `is_spt_hosted_no_relay` inject target. fn seed_bound_perch(id: &str, session_id: &str) { @@ -103,8 +101,22 @@ fn boundary_restamps_ready_after_soft_session_end() { // ── The pre-boundary soft session-end (CC fires it for the departing session, // whose sid still matches the pin → authenticates → removes the ready // marker). REAL `api session-end` with the pinned sid as auth proof. ── - let end = spt(&["api", "--adapter", "dummyharness", "--manifest", &mp, "session-end", id, "--session-id", sid]); - assert!(end.status.success(), "soft session-end: {}", String::from_utf8_lossy(&end.stderr)); + let end = spt(&[ + "api", + "--adapter", + "dummyharness", + "--manifest", + &mp, + "session-end", + id, + "--session-id", + sid, + ]); + assert!( + end.status.success(), + "soft session-end: {}", + String::from_utf8_lossy(&end.stderr) + ); assert!(!ready.exists(), "soft session-end removed the ready marker"); assert!( !spt_daemon::is_spt_hosted_no_relay(id, &owlery), @@ -115,14 +127,24 @@ fn boundary_restamps_ready_after_soft_session_end() { // clear`; auth proof = the still-current pin (sid), --to-session-id = the // successor. ── let boundary = spt(&[ - "api", "--adapter", "dummyharness", "--manifest", &mp, - "boundary", "clear", id, "--to-session-id", new_sid, "--session-id", sid, + "api", + "--adapter", + "dummyharness", + "--manifest", + &mp, + "boundary", + "clear", + id, + "--to-session-id", + new_sid, + "--session-id", + sid, ]); let b_err = String::from_utf8_lossy(&boundary.stderr).to_string(); let ready_after = ready.exists(); let target_after = spt_daemon::is_spt_hosted_no_relay(id, &owlery); - let sid_after = info::read_info(&perch::resolve_perch_path(id, ParentHint::Infer)) - .map(|r| r.session_id); + let sid_after = + info::read_info(&perch::resolve_perch_path(id, ParentHint::Infer)).map(|r| r.session_id); eprintln!( "=== F029 C-2 DIAGNOSTIC: boundary_exit={:?} ready_after={ready_after} \ target_after={target_after} sid_after={sid_after:?} ===\n{b_err}", @@ -137,11 +159,18 @@ fn boundary_restamps_ready_after_soft_session_end() { assert!(boundary.status.success(), "boundary must succeed:\n{b_err}"); // The rotation happened (the pin advanced to the successor). - assert_eq!(sid_after.as_deref(), Some(new_sid), "the boundary rotated the sid"); + assert_eq!( + sid_after.as_deref(), + Some(new_sid), + "the boundary rotated the sid" + ); // The load-bearing claim (C-2): the boundary RE-STAMPED ready, so the rotated // perch is a live inject target again — the checkpoint FIRE can land. // [int->REQ-HAZARD-BOUNDARY-READY-STRAND] - assert!(ready_after, "the boundary must RE-STAMP the ready marker (C-2)"); + assert!( + ready_after, + "the boundary must RE-STAMP the ready marker (C-2)" + ); assert!( target_after, "after the boundary the perch is a live inject target again — the post-clear \ diff --git a/crates/spt/tests/brain_respawn_rename.rs b/crates/spt/tests/brain_respawn_rename.rs index ab4abaec..7a264bc0 100644 --- a/crates/spt/tests/brain_respawn_rename.rs +++ b/crates/spt/tests/brain_respawn_rename.rs @@ -130,7 +130,8 @@ fn brain_respawns_onto_applied_bytes_after_in_place_rename() { .append(true) .open(&canonical) .expect("open the new P to append padding"); - f.write_all(&[0u8; 4096]).expect("append padding -> bytes B"); + f.write_all(&[0u8; 4096]) + .expect("append padding -> bytes B"); } let hash_b = file_hash(&canonical); assert_ne!(hash_a, hash_b, "the swap must flip the binary hash"); @@ -142,11 +143,12 @@ fn brain_respawns_onto_applied_bytes_after_in_place_rename() { // rename to P.old-8 and respawns bytes A → this assert fails; post-fix it // spawns the captured P (bytes B). Windows never followed the rename. ── kill_pid(pid0); - let (pid1, hash1) = wait_ready(&ready, Some(pid0), Duration::from_secs(45)).unwrap_or_else(|| { - kill_pid(pid0); - let _ = broker.kill(); - panic!("supervisor never respawned the brain after the rename"); - }); + let (pid1, hash1) = + wait_ready(&ready, Some(pid0), Duration::from_secs(45)).unwrap_or_else(|| { + kill_pid(pid0); + let _ = broker.kill(); + panic!("supervisor never respawned the brain after the rename"); + }); assert_ne!(pid0, pid1, "the respawned brain is a fresh process"); assert_eq!( hash1.as_deref(), diff --git a/crates/spt/tests/brain_survive.rs b/crates/spt/tests/brain_survive.rs index bfad8e28..48c439d4 100644 --- a/crates/spt/tests/brain_survive.rs +++ b/crates/spt/tests/brain_survive.rs @@ -203,7 +203,10 @@ fn pty_and_quic_survive_brain_process_restart_onto_swapped_binary() { // Both are the real `spt` binary, so `daemon brain` runs; B differs only by // trailing bytes (behavior identical, exe_hash flips). let spt_bin = PathBuf::from(env!("CARGO_BIN_EXE_spt")); - let suffix = spt_bin.extension().map(|e| format!(".{}", e.to_string_lossy())).unwrap_or_default(); + let suffix = spt_bin + .extension() + .map(|e| format!(".{}", e.to_string_lossy())) + .unwrap_or_default(); let fixture_a = home.path().join(format!("brain-A{suffix}")); let fixture_b = home.path().join(format!("brain-B{suffix}")); std::fs::copy(&spt_bin, &fixture_a).expect("stage fixture A"); @@ -214,14 +217,19 @@ fn pty_and_quic_survive_brain_process_restart_onto_swapped_binary() { .append(true) .open(&fixture_b) .expect("open fixture B to append padding"); - f.write_all(&[0u8; 4096]).expect("append padding to fixture B"); + f.write_all(&[0u8; 4096]) + .expect("append padding to fixture B"); } let hash_a = file_hash(&fixture_a); let hash_b = file_hash(&fixture_b); assert_ne!(hash_a, hash_b, "the swap must flip the binary hash"); // ── The broker (leg-b stable kernel) + a loopback QUIC peer. ── - let broker = net_broker(&broker_socket_name(), Identity::generate(), &home.path().join("a")); + let broker = net_broker( + &broker_socket_name(), + Identity::generate(), + &home.path().join("a"), + ); let peer_name = format!("spt-d7-peer-{}.sock", std::process::id()); let _peer = net_broker(&peer_name, Identity::generate(), &home.path().join("b")); @@ -232,7 +240,9 @@ fn pty_and_quic_survive_brain_process_restart_onto_swapped_binary() { let mut driver = connect_retry(&broker_socket_name()); // (1) A hosted PTY child the broker holds. - let sid = driver.spawn_session(echo_spawn_req()).expect("spawn session"); + let sid = driver + .spawn_session(echo_spawn_req()) + .expect("spawn session"); let child_pid = broker.session_pid(sid).expect("hosted child has a pid"); // (2) A live QUIC connection the broker holds: dial the loopback peer. @@ -240,7 +250,9 @@ fn pty_and_quic_survive_brain_process_restart_onto_swapped_binary() { let mut peer_brain = connect_retry(&peer_name); peer_brain.net_status().expect("peer status").addr }; - driver.net_dial(peer_addr, None).expect("dial the loopback peer"); + driver + .net_dial(peer_addr, None) + .expect("dial the loopback peer"); // Both endpoints are now broker-held. assert_eq!(broker.session_count(), 1, "one hosted session established"); @@ -298,13 +310,21 @@ fn pty_and_quic_survive_brain_process_restart_onto_swapped_binary() { Some(hash_a.as_str()), "gen-0 brain.ready exe_hash must be fixture A" ); - assert_eq!(broker.session_count(), 1, "session survived the driver drop + resume"); + assert_eq!( + broker.session_count(), + 1, + "session survived the driver drop + resume" + ); assert_eq!( broker.session_pid(sid), Some(child_pid), "the PTY child's pid is unchanged through the resume" ); - assert_eq!(broker.net_conn_count(), 1, "the QUIC conn survived the driver drop"); + assert_eq!( + broker.net_conn_count(), + 1, + "the QUIC conn survived the driver drop" + ); // ── SWAP: flip the selected binary to B, then trigger a planned restart // (what `apply` does: swap on disk, signal the brain to cycle). ── @@ -335,7 +355,11 @@ fn pty_and_quic_survive_brain_process_restart_onto_swapped_binary() { Some(child_pid), "REQ-UPD-3: the hosted PTY child's pid is unchanged across the brain-process swap" ); - assert_eq!(broker.session_count(), 1, "exactly one hosted session throughout"); + assert_eq!( + broker.session_count(), + 1, + "exactly one hosted session throughout" + ); assert_eq!( broker.net_conn_count(), 1, @@ -349,9 +373,9 @@ fn pty_and_quic_survive_brain_process_restart_onto_swapped_binary() { // a zombie handle merely lingers. The input rides the KIND_INPUT effect verb // on a FRESH raw connection, which does NOT steal the supervised brain's // output subscription (it is not an attach). ── - let seq_before = broker - .session_output_seq(sid) - .unwrap_or_else(|| teardown_panic(&stop, "hosted session vanished before the functional probe")); + let seq_before = broker.session_output_seq(sid).unwrap_or_else(|| { + teardown_panic(&stop, "hosted session vanished before the functional probe") + }); { let mut raw = LocalSocketTransport::connect(&broker_socket_name()) .unwrap_or_else(|_| teardown_panic(&stop, "could not open a raw input connection")); @@ -366,7 +390,10 @@ fn pty_and_quic_survive_brain_process_restart_onto_swapped_binary() { }; write_frame( &mut raw, - &Envelope::new(KIND_INPUT, serde_json::to_value(input).expect("InputReq serializes")), + &Envelope::new( + KIND_INPUT, + serde_json::to_value(input).expect("InputReq serializes"), + ), ) .unwrap_or_else(|_| teardown_panic(&stop, "could not write the marker input frame")); } @@ -375,7 +402,11 @@ fn pty_and_quic_survive_brain_process_restart_onto_swapped_binary() { let mut advanced = false; let deadline = Instant::now() + Duration::from_secs(15); while Instant::now() < deadline { - if broker.session_output_seq(sid).map(|s| s > seq_before).unwrap_or(false) { + if broker + .session_output_seq(sid) + .map(|s| s > seq_before) + .unwrap_or(false) + { advanced = true; break; } diff --git a/crates/spt/tests/broker_stop_endpoint_deny_e2e.rs b/crates/spt/tests/broker_stop_endpoint_deny_e2e.rs index d6e36a1e..86601852 100644 --- a/crates/spt/tests/broker_stop_endpoint_deny_e2e.rs +++ b/crates/spt/tests/broker_stop_endpoint_deny_e2e.rs @@ -132,10 +132,7 @@ fn an_endpoint_context_cannot_stop_the_broker_by_any_flag() { ); // ── Leg 1: EVERY flag combination refuses, daemon survives each. ──── - for args in [ - &["daemon", "stop"][..], - &["daemon", "stop", "--force"][..], - ] { + for args in [&["daemon", "stop"][..], &["daemon", "stop", "--force"][..]] { let (code, err) = as_endpoint(home, args); assert_ne!(code, 0, "{args:?} must not succeed for an endpoint: {err}"); assert!( @@ -173,7 +170,10 @@ fn an_endpoint_context_cannot_stop_the_broker_by_any_flag() { err.contains("UPDATE_FINISH_REFUSED"), "the finish leg refuses for an endpoint: {err}" ); - assert!(daemon_running(home), "the daemon survives the finish attempt"); + assert!( + daemon_running(home), + "the daemon survives the finish attempt" + ); // ── Leg 4: CONTEXT-scoped, not global. Same binary, same home, no // endpoint marker ⇒ the human contract still works. Without this the diff --git a/crates/spt/tests/common/reap.rs b/crates/spt/tests/common/reap.rs index 7e84d63e..bc9f9ad5 100644 --- a/crates/spt/tests/common/reap.rs +++ b/crates/spt/tests/common/reap.rs @@ -146,7 +146,10 @@ pub fn authenticated_kill( return refuse("gone", "the breadcrumb outlived its writer".to_string()) } ProcIdentity::Unproven => { - return refuse("unproven-identity", "no creation time to compare".to_string()) + return refuse( + "unproven-identity", + "no creation time to compare".to_string(), + ) } ProcIdentity::Present(started_at) => started_at, }; @@ -154,7 +157,10 @@ pub fn authenticated_kill( if obs.started_at != started_at { return refuse( "reused", - format!("observed_started_at={} current={started_at}", obs.started_at), + format!( + "observed_started_at={} current={started_at}", + obs.started_at + ), ); } } diff --git a/crates/spt/tests/commune_two_cwd_e2e.rs b/crates/spt/tests/commune_two_cwd_e2e.rs index 10ec2995..9034c18b 100644 --- a/crates/spt/tests/commune_two_cwd_e2e.rs +++ b/crates/spt/tests/commune_two_cwd_e2e.rs @@ -166,7 +166,10 @@ fn a_commune_written_from_a_worktree_is_loud_and_stale_while_the_registered_one_ let out = download(); let stdout = String::from_utf8_lossy(&out.stdout).to_string(); let stderr = String::from_utf8_lossy(&out.stderr).to_string(); - eprintln!("=== leg A (misplaced) ===\nstatus={}\n{stdout}\n--stderr--\n{stderr}", out.status); + eprintln!( + "=== leg A (misplaced) ===\nstatus={}\n{stdout}\n--stderr--\n{stderr}", + out.status + ); // ── LEG B: the SAME bytes, in the dir the ingest watches ── std::fs::rename(&misplaced, &placed).expect("move the drop into the watched dir"); @@ -187,7 +190,10 @@ fn a_commune_written_from_a_worktree_is_loud_and_stale_while_the_registered_one_ .env("SPT_AGENT_ID", id); let listing = common::output_bounded(cmd, Duration::from_secs(30)); let listed = String::from_utf8_lossy(&listing.stdout).to_string(); - eprintln!("=== leg C (endpoint list --json) ===\nstatus={}\n{listed}", listing.status); + eprintln!( + "=== leg C (endpoint list --json) ===\nstatus={}\n{listed}", + listing.status + ); // ── Teardown, ahead of every assertion ── let observed = reap::breadcrumb_daemon_pid(home.path()) @@ -282,7 +288,10 @@ fn a_commune_written_from_a_worktree_is_loud_and_stale_while_the_registered_one_ // file on disk means either an ingest that errored or a drop written from a // cwd nothing watches, and until this field existed no surface said which // dir was watched. - assert!(listing.status.success(), "endpoint list --json must succeed: {listing:?}"); + assert!( + listing.status.success(), + "endpoint list --json must succeed: {listing:?}" + ); let doc: serde_json::Value = serde_json::from_str(&listed).expect("valid JSON listing"); let self_pin = doc.get("self").expect("the listing carries a self pin"); assert_eq!( diff --git a/crates/spt/tests/composite_e2e.rs b/crates/spt/tests/composite_e2e.rs index ca285e9b..582f275d 100644 --- a/crates/spt/tests/composite_e2e.rs +++ b/crates/spt/tests/composite_e2e.rs @@ -37,8 +37,6 @@ fn hex(bytes: &[u8]) -> String { bytes.iter().map(|b| format!("{b:02x}")).collect() } - - /// The signed update set the fake channel serves: one artifact for the CURRENT /// platform (fetch requires `asset_name`), product 9.9.9, docs-less. fn signed_set_json(version: u64, artifact: &[u8]) -> String { @@ -144,9 +142,17 @@ fn bare_update_applies_core_then_updates_adapter_in_one_invocation() { let assets = gh_root.join("assets"); std::fs::create_dir_all(&assets).unwrap(); std::fs::write(gh_root.join("tag.txt"), "v1.1.0").unwrap(); - std::fs::write(assets.join("update-set.json"), signed_set_json(1, NEW_CORE_BYTES)).unwrap(); + std::fs::write( + assets.join("update-set.json"), + signed_set_json(1, NEW_CORE_BYTES), + ) + .unwrap(); std::fs::write(assets.join("spt-composite-artifact"), NEW_CORE_BYTES).unwrap(); - std::fs::write(assets.join("adapter.spt"), adapter_spt(root.path(), "1.1.0")).unwrap(); + std::fs::write( + assets.join("adapter.spt"), + adapter_spt(root.path(), "1.1.0"), + ) + .unwrap(); let gh_log = root.path().join("gh.log"); // ── (3) Register the gh_release adapter `cc` at 1.0.0 (its install dir is @@ -155,8 +161,7 @@ fn bare_update_applies_core_then_updates_adapter_in_one_invocation() { let install_dir = spt_store::perch::spt_home().join("srcs").join("cc"); std::fs::create_dir_all(&install_dir).unwrap(); std::fs::write(install_dir.join("manifest.toml"), adapter_manifest("1.0.0")).unwrap(); - spt_runtime::registry::register(&spt_store::perch::adapters_dir(), &install_dir, 1000) - .unwrap(); + spt_runtime::registry::register(&spt_store::perch::adapters_dir(), &install_dir, 1000).unwrap(); std::env::remove_var("SPT_HOME"); // ── (4) ONE invocation: bare `spt update`. ── diff --git a/crates/spt/tests/contract_e2e.rs b/crates/spt/tests/contract_e2e.rs index c16cca56..00365da0 100644 --- a/crates/spt/tests/contract_e2e.rs +++ b/crates/spt/tests/contract_e2e.rs @@ -57,7 +57,6 @@ fn start_inproc_daemon() { panic!("in-process seed daemon did not come up"); } - #[test] fn mock_adapter_drives_the_full_contract() { let _serial = E2E_LOCK.lock().unwrap_or_else(|e| e.into_inner()); @@ -129,7 +128,8 @@ fn mock_adapter_drives_the_full_contract() { spool::spool_message_at(&perch_path, "tester", "hello over the contract").unwrap(); // Inbound assertion 3 — `api poll` drains it (the full delivery round-trip). - let poll = Command::new(&spt_bin).no_window() + let poll = Command::new(&spt_bin) + .no_window() .args([ "api", "--adapter", @@ -151,7 +151,8 @@ fn mock_adapter_drives_the_full_contract() { // Auth negative — a poll with no proof is refused (REQ-HAZARD-LOCAL-API-AUTH // exercised through the real binary). - let unauth = Command::new(&spt_bin).no_window() + let unauth = Command::new(&spt_bin) + .no_window() .args(["api", "--adapter", "mock", "poll", id]) .env("SPT_HOME", home.path()) .env_remove("OWL_SESSION_ID") @@ -185,7 +186,8 @@ fn seed_then_listen_binds_and_relays() { spool::spool_message_at(&perch_path, "tester", "delivered via listen").unwrap(); // Seed the startup record keyed by the anchor pid. - let seed = Command::new(&spt_bin).no_window() + let seed = Command::new(&spt_bin) + .no_window() .args([ "api", "--adapter", @@ -203,7 +205,8 @@ fn seed_then_listen_binds_and_relays() { // Listen consumes the seed (explicit --parent-pid for a deterministic match), // binds the perch, drains the backlog, and exits (--once). - let listen = Command::new(&spt_bin).no_window() + let listen = Command::new(&spt_bin) + .no_window() .args([ "api", "--adapter", @@ -294,7 +297,8 @@ fn live_agent_lifecycle_e2e() { let anchor = std::process::id().to_string(); // Seed the startup record keyed by the anchor pid. - let seed = Command::new(&spt_bin).no_window() + let seed = Command::new(&spt_bin) + .no_window() .args([ "api", "--adapter", @@ -335,7 +339,8 @@ fn live_agent_lifecycle_e2e() { // Listen (live-capable manifest): M11-W0.2 — BINDS the perch and marks it // status=online (the first-host handoff); the Psyche/pulse no longer spawn in // THIS process. The brain hosts the lifecycle (driven below). - let listen = Command::new(&spt_bin).no_window() + let listen = Command::new(&spt_bin) + .no_window() .args([ "api", "--adapter", @@ -408,7 +413,8 @@ fn live_agent_lifecycle_e2e() { } // 3. Graceful shutdown fires the echo-commune BEFORE teardown (3.3). - let shutdown = Command::new(&spt_bin).no_window() + let shutdown = Command::new(&spt_bin) + .no_window() .args([ "api", "--adapter", @@ -475,7 +481,8 @@ fn cold_api_call_autostarts_daemon_and_handoff_is_in_memory() { spool::spool_message_at(&perch_path, "tester", "delivered after cold start").unwrap(); // Cold seed — auto-starts the daemon and PUTs the seed into its memory. - let seed = Command::new(&spt_bin).no_window() + let seed = Command::new(&spt_bin) + .no_window() .args([ "api", "--adapter", @@ -510,7 +517,8 @@ fn cold_api_call_autostarts_daemon_and_handoff_is_in_memory() { ); // Listen TAKEs the seed from the daemon, binds, drains the backlog, exits. - let listen = Command::new(&spt_bin).no_window() + let listen = Command::new(&spt_bin) + .no_window() .args([ "api", "--adapter", diff --git a/crates/spt/tests/coordinator_image_e2e.rs b/crates/spt/tests/coordinator_image_e2e.rs index a800001e..77e43383 100644 --- a/crates/spt/tests/coordinator_image_e2e.rs +++ b/crates/spt/tests/coordinator_image_e2e.rs @@ -146,9 +146,7 @@ fn the_running_coordinator_reports_its_compiled_image_and_no_impostor_can() { }; let reported = wait_coordinator_image(&broker_socket_name(), Duration::from_secs(45)) - .unwrap_or_else(|| { - teardown_panic(&stop, "the live coordinator never reported its image") - }); + .unwrap_or_else(|| teardown_panic(&stop, "the live coordinator never reported its image")); // The version the brain PROCESS was compiled at — which for this build is the // workspace version the CLI compares against. Sourced from the running // process: nothing was read off disk to produce it. diff --git a/crates/spt/tests/create_bind_rest_active_e2e.rs b/crates/spt/tests/create_bind_rest_active_e2e.rs index 4a6055fc..140cae79 100644 --- a/crates/spt/tests/create_bind_rest_active_e2e.rs +++ b/crates/spt/tests/create_bind_rest_active_e2e.rs @@ -47,8 +47,6 @@ fn start_inproc_daemon() { panic!("in-process seed daemon did not come up"); } - - /// The HARNESS-HOSTED live perch an `api listen` leaves: online, a ready marker, /// `controllable` unset (no broker PTY). The owner pid is a never-allocated one — /// the harness of a life that is about to be stopped is gone by the time the NEXT @@ -98,14 +96,16 @@ fn a_fresh_bind_after_a_real_stop_comes_up_active_without_a_wake() { seed_harness_hosted_online(id, "sid-life-1"); // ── THE STOP (real verb). Its terminal normalize IS what writes the residue. ── - let stop = common::output_bounded({ - let mut cmd = Command::new(&spt_bin); - cmd.no_window() - .args(["endpoint", "stop", id]) - .env("SPT_HOME", home.path()); - cmd - }, - Duration::from_secs(60),); + let stop = common::output_bounded( + { + let mut cmd = Command::new(&spt_bin); + cmd.no_window() + .args(["endpoint", "stop", id]) + .env("SPT_HOME", home.path()); + cmd + }, + Duration::from_secs(60), + ); assert!( stop.status.success(), "endpoint stop must succeed on an evidenced endpoint: stdout={} stderr={}", @@ -126,26 +126,28 @@ fn a_fresh_bind_after_a_real_stop_comes_up_active_without_a_wake() { // ── THE FRESH LIFE (real verb): a new session binds over the stopped one, which // is where `endpoint start` lands. No wake in between. ── - let bind = common::output_bounded({ - let mut cmd = Command::new(&spt_bin); - cmd.no_window() - .args([ - "api", - "--adapter", - "dummyharness", - "--manifest", - &mp, - "bind", - id, - "--type", - "live_agent", - "--set-session-id", - "sid-life-2", - ]) - .env("SPT_HOME", home.path()); - cmd - }, - Duration::from_secs(60),); + let bind = common::output_bounded( + { + let mut cmd = Command::new(&spt_bin); + cmd.no_window() + .args([ + "api", + "--adapter", + "dummyharness", + "--manifest", + &mp, + "bind", + id, + "--type", + "live_agent", + "--set-session-id", + "sid-life-2", + ]) + .env("SPT_HOME", home.path()); + cmd + }, + Duration::from_secs(60), + ); assert!( bind.status.success(), "the fresh bind must succeed: stdout={} stderr={}", @@ -154,7 +156,10 @@ fn a_fresh_bind_after_a_real_stop_comes_up_active_without_a_wake() { ); let after = record(id); - assert_eq!(after.session_id, "sid-life-2", "the new life owns the perch"); + assert_eq!( + after.session_id, "sid-life-2", + "the new life owns the perch" + ); assert_eq!( after.status.as_deref(), Some("online"), diff --git a/crates/spt/tests/daemon_refresh_e2e.rs b/crates/spt/tests/daemon_refresh_e2e.rs index fe88b7ce..6c7a04a5 100644 --- a/crates/spt/tests/daemon_refresh_e2e.rs +++ b/crates/spt/tests/daemon_refresh_e2e.rs @@ -56,8 +56,6 @@ fn wait_ready_not(path: &Path, was: Option, budget: Duration) -> Option<(u3 None } - - #[test] fn daemon_refresh_cycles_brain_while_hosted_endpoint_survives() { let now_ms = || { diff --git a/crates/spt/tests/docs_bundle_e2e.rs b/crates/spt/tests/docs_bundle_e2e.rs index b0c40305..1791c4bd 100644 --- a/crates/spt/tests/docs_bundle_e2e.rs +++ b/crates/spt/tests/docs_bundle_e2e.rs @@ -29,7 +29,11 @@ fn hex(bytes: &[u8]) -> String { /// A signed update set for the CURRENT platform whose docs entry matches /// `docs_sha` (`None` ⇒ docs-less set). -fn signed_set(version: u64, artifact: &[u8], docs_sha: Option) -> spt_daemon::SignedUpdateSet { +fn signed_set( + version: u64, + artifact: &[u8], + docs_sha: Option, +) -> spt_daemon::SignedUpdateSet { let meta = spt_daemon::UpdateSetMetadata { version, channel: "stable".to_string(), @@ -150,8 +154,13 @@ fn docs_land_on_apply_and_docs_failure_never_touches_the_binary_outcome() { // Leg 1 — happy path: signed docs entry + matching staged bundle ⇒ apply // lands the version-matched tree at $SPT_HOME/docs and clears the stage. let (home1, spt1) = fresh_home(tmp.path(), "node-good"); - let (ok, stdout, stderr, swapped) = - stage_and_apply(&home1, &spt1, &artifact, Some(bundle_sha.clone()), Some(&bundle)); + let (ok, stdout, stderr, swapped) = stage_and_apply( + &home1, + &spt1, + &artifact, + Some(bundle_sha.clone()), + Some(&bundle), + ); assert!(ok, "apply must succeed: {stderr}"); assert!( stdout.contains("UPDATE_DOCS_LANDED"), @@ -186,7 +195,10 @@ fn docs_land_on_apply_and_docs_failure_never_touches_the_binary_outcome() { Some(bundle_sha), Some(b"NOT-THE-SIGNED-BYTES"), ); - assert!(ok2, "binary apply must succeed despite docs failure: {stderr2}"); + assert!( + ok2, + "binary apply must succeed despite docs failure: {stderr2}" + ); assert!( stderr2.contains("UPDATE_DOCS_SKIPPED"), "distinct skip token on stderr: {stderr2}" @@ -208,8 +220,7 @@ fn docs_land_on_apply_and_docs_failure_never_touches_the_binary_outcome() { // Leg 3 — a docs-less set stays exactly the pre-docs behavior: no token // either way, binary applies. let (home3, spt3) = fresh_home(tmp.path(), "node-docsless"); - let (ok3, stdout3, stderr3, swapped3) = - stage_and_apply(&home3, &spt3, &artifact, None, None); + let (ok3, stdout3, stderr3, swapped3) = stage_and_apply(&home3, &spt3, &artifact, None, None); assert!(ok3, "docs-less apply succeeds: {stderr3}"); assert!( !stdout3.contains("UPDATE_DOCS") && !stderr3.contains("UPDATE_DOCS"), diff --git a/crates/spt/tests/drive_e2e.rs b/crates/spt/tests/drive_e2e.rs index 5315dfb1..29f8b66f 100644 --- a/crates/spt/tests/drive_e2e.rs +++ b/crates/spt/tests/drive_e2e.rs @@ -123,9 +123,8 @@ fn drive_channel_slot_through_the_real_socket() { let owlery = perch::owlery_dir(); let shell_perch = perch::resolve_shell_perch_path_in(&owlery, "doyle", "mock-shell-0"); - let token_of = || { - spt_daemon::shellhost::read_link_token(&shell_perch).expect("a link token is parked") - }; + let token_of = + || spt_daemon::shellhost::read_link_token(&shell_perch).expect("a link token is parked"); let drive = |drive_type: &str, payload: &str| { spt(&[ "shell", "drive", "Scout", "--type", drive_type, payload, "--owner", "doyle", @@ -164,14 +163,23 @@ fn drive_channel_slot_through_the_real_socket() { // ── spawn: the noop binary exits, the perch stays offline; a token is parked. let out = spt(&[ - "shell", "spawn", "mock-shell", "--alias", "Scout", "--owner", "doyle", + "shell", + "spawn", + "mock-shell", + "--alias", + "Scout", + "--owner", + "doyle", ]); assert!( out.status.success(), "spawn: {}", String::from_utf8_lossy(&out.stderr) ); - assert!(!is_online(), "the noop binary never binds — perch starts offline"); + assert!( + !is_online(), + "the noop binary never binds — perch starts offline" + ); // FIXTURE INTENT (REQ-HAZARD-SHELL-STALE-ONLINE): this suite models a LIVE // linked binary — the test process drives the link through `api drive-poll` // exactly as the resident would. But the spawn template is a noop that already @@ -191,7 +199,10 @@ fn drive_channel_slot_through_the_real_socket() { // ── (1) DROP-AT-WRITE: driving an offline shell drops (exit 0, diagnostic), // writes no slot — the poll comes back empty. let out = drive("stick", "x=0.1"); - assert!(out.status.success(), "an offline drive is a defined drop (exit 0)"); + assert!( + out.status.success(), + "an offline drive is a defined drop (exit 0)" + ); assert!( String::from_utf8_lossy(&out.stderr).contains("DRIVE_DROPPED"), "offline drive diagnoses a drop: {}", @@ -213,7 +224,10 @@ fn drive_channel_slot_through_the_real_socket() { assert!(drive("stick", "x=0.9").status.success()); let out = drive_poll(&token_a); let frame = String::from_utf8_lossy(&out.stdout); - assert!(frame.contains("type=\"drive\""), "served the drive frame: {frame}"); + assert!( + frame.contains("type=\"drive\""), + "served the drive frame: {frame}" + ); assert!( frame.contains("x=0.9") && !frame.contains("x=0.1"), "the latest write superseded the earlier one: {frame}" @@ -237,11 +251,16 @@ fn drive_channel_slot_through_the_real_socket() { // leaves no `drive` artifact under the perch (the real guarantee is // by-construction — DriveHub is an in-memory map, no fs/serde). assert!(drive("stick", "x=0.4").status.success()); - let no_drive_file = std::fs::read_dir(&shell_perch) - .unwrap() - .flatten() - .all(|e| !e.file_name().to_string_lossy().to_lowercase().contains("drive")); - assert!(no_drive_file, "the drive slot is held in memory, not a perch file"); + let no_drive_file = std::fs::read_dir(&shell_perch).unwrap().flatten().all(|e| { + !e.file_name() + .to_string_lossy() + .to_lowercase() + .contains("drive") + }); + assert!( + no_drive_file, + "the drive slot is held in memory, not a perch file" + ); // ── (5) CLEAR-ON-LINK-BREAK: a frame written while online must NEVER be // served to the relinked instance. Break the link (close_shell flips offline, diff --git a/crates/spt/tests/dummy_harness_e2e.rs b/crates/spt/tests/dummy_harness_e2e.rs index 788b3d80..9d968e38 100644 --- a/crates/spt/tests/dummy_harness_e2e.rs +++ b/crates/spt/tests/dummy_harness_e2e.rs @@ -48,8 +48,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - fn ready_pid(path: &Path) -> Option { let s = std::fs::read_to_string(path).ok()?; serde_json::from_str::(&s) @@ -70,8 +68,6 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - #[test] fn endpoint_run_brings_up_a_long_lived_dummy_harness_and_rc_attaches() { // Serialize against the sister test — shared process-global SPT_HOME. @@ -141,18 +137,18 @@ fn endpoint_run_brings_up_a_long_lived_dummy_harness_and_rc_attaches() { .stderr(Stdio::from(brain_log_file)) .spawn() .expect("spawn spt daemon run (broker process)"); - let brain_pid = match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(30)) - { - Some(p) => p, - None => { - let _ = broker.kill(); - let _ = broker.wait(); - panic!( - "PRECONDITION: brain never came up.\n{}", - common::daemon_stderr_panel(&brain_log) - ); - } - }; + let brain_pid = + match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(30)) { + Some(p) => p, + None => { + let _ = broker.kill(); + let _ = broker.wait(); + panic!( + "PRECONDITION: brain never came up.\n{}", + common::daemon_stderr_panel(&brain_log) + ); + } + }; // ── (4) The REAL spt-hosted bringup: endpoint create + start (broker spawns the // dummy into a PTY; the dummy binds its perch + heartbeats). ── @@ -192,7 +188,9 @@ fn endpoint_run_brings_up_a_long_lived_dummy_harness_and_rc_attaches() { .and_then(|s| s.trim().parse().ok()); let alive_after = { std::thread::sleep(Duration::from_millis(700)); - harness_pid.map(spt_store::proc::is_process_alive).unwrap_or(false) + harness_pid + .map(spt_store::proc::is_process_alive) + .unwrap_or(false) }; // ── (5) rc ATTACH: stream the live PTY output; assert the heartbeat arrives. ── @@ -260,14 +258,15 @@ fn endpoint_run_brings_up_a_long_lived_dummy_harness_and_rc_attaches() { kill_pid(p); } // The reconcile may have hosted a `{id}-psyche` — reap it too (scoped). - let psyche_perch = - perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); + let psyche_perch = perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); if let Some(p) = spt_store::info::read_pid(&psyche_perch) { kill_pid(p); } let _ = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -565,8 +564,7 @@ fn endpoint_run_attach_awaits_online_before_attaching() { if let Some(p) = harness_pid_2 { kill_pid(p); } - let psyche_perch = - perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); + let psyche_perch = perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); if let Some(p) = spt_store::info::read_pid(&psyche_perch) { kill_pid(p); } diff --git a/crates/spt/tests/endpoint_autostart_e2e.rs b/crates/spt/tests/endpoint_autostart_e2e.rs index 3a121738..24dd1d51 100644 --- a/crates/spt/tests/endpoint_autostart_e2e.rs +++ b/crates/spt/tests/endpoint_autostart_e2e.rs @@ -100,8 +100,6 @@ fn wait_for_ready_pid(path: &Path, not: Option, budget: Duration) -> Option None } - - /// Concatenate every file under `/logs` — the daemon redirects its OWN /// stderr FD in-process to `logs/daemon.stderr.log` (+ rolled `.1`), so the /// broker/brain's `eprintln!` diagnostics (incl. `ENDPOINT_AUTOSTART:`) land @@ -375,8 +373,7 @@ fn saved_endpoint_replays_on_daemon_restart() { reaper.add(pid); kill_pid(pid); } - let psyche_perch = - perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); + let psyche_perch = perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); if let Some(pid) = spt_store::info::read_pid(&psyche_perch) { reaper.add(pid); kill_pid(pid); @@ -429,7 +426,8 @@ fn saved_endpoint_replays_on_daemon_restart() { session_b = spt_store::info::read_info(&self_perch).map(|r| r.session_id); // Done once the loud token is present AND the perch carries a fresh // (post-restart) session id distinct from run A's. - let fresh = matches!((&session_a, &session_b), (Some(a), Some(b)) if !b.is_empty() && a != b); + let fresh = + matches!((&session_a, &session_b), (Some(a), Some(b)) if !b.is_empty() && a != b); if autostart_line.is_some() && fresh { break; } diff --git a/crates/spt/tests/endpoint_teardown_authority_e2e.rs b/crates/spt/tests/endpoint_teardown_authority_e2e.rs index 1e841f33..38431f64 100644 --- a/crates/spt/tests/endpoint_teardown_authority_e2e.rs +++ b/crates/spt/tests/endpoint_teardown_authority_e2e.rs @@ -62,7 +62,9 @@ use spt_store::perch::{self, ParentHint}; static ENV_LOCK: Mutex<()> = Mutex::new(()); fn env_lock() -> MutexGuard<'static, ()> { - ENV_LOCK.lock().unwrap_or_else(|poisoned| poisoned.into_inner()) + ENV_LOCK + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()) } fn kill_pid(pid: u32) { @@ -75,8 +77,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - fn ready_pid(path: &Path) -> Option { let s = std::fs::read_to_string(path).ok()?; serde_json::from_str::(&s) @@ -115,8 +115,6 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - fn wait_for_status(id: &str, want: &str, budget: Duration) -> bool { let perch = perch::resolve_perch_path(id, ParentHint::Infer); let deadline = Instant::now() + budget; @@ -589,8 +587,8 @@ fn stop_reaps_the_hosted_subtree_and_run_recovers_the_endpoint() { // Same shape as a bringup, so the same observation contract: the ANNOUNCED // row on the shared bringup budget. let sessions_after_resume = wait_for_announced_session(id, resumed_pid, BRINGUP_OBSERVE); - let resumed_descendant = wait_for_file(&rig.descendant_marker, BRINGUP_OBSERVE) - .and_then(|s| s.parse::().ok()); + let resumed_descendant = + wait_for_file(&rig.descendant_marker, BRINGUP_OBSERVE).and_then(|s| s.parse::().ok()); let brain_stderr = rig.diagnostics(); // WHICH LEG of each bringup completed. `sessions` empty reads the same @@ -741,7 +739,11 @@ fn stop_reaps_the_hosted_subtree_and_run_recovers_the_endpoint() { ); // ── …and the RESUME shape of the same recovery. ── - assert_eq!(stop2_code, Some(0), "the recovered endpoint stops cleanly too"); + assert_eq!( + stop2_code, + Some(0), + "the recovered endpoint stops cleanly too" + ); assert!( survivors2.is_empty(), "the recovered endpoint's subtree is reaped as well — the fix is not one-shot: {survivors2:?}" diff --git a/crates/spt/tests/engine_room_bringup_e2e.rs b/crates/spt/tests/engine_room_bringup_e2e.rs index f7422e36..e0420b72 100644 --- a/crates/spt/tests/engine_room_bringup_e2e.rs +++ b/crates/spt/tests/engine_room_bringup_e2e.rs @@ -63,8 +63,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - /// `brain.ready` carries a JSON object (`{"pid":…,"generation":…}`), not a bare /// pid — `brainproc::write_ready`. Parsed as JSON so a partial write reads as /// "not ready yet" rather than as a malformed pid. @@ -108,7 +106,9 @@ fn seed_subnet_and_code(name: &str) -> String { let store = spt_store::subnet::SubnetStore::load(); let rec = store.find(name).expect("the subnet we just created"); - let seed = rec.seed_bytes().expect("a created subnet carries a member seed"); + let seed = rec + .seed_bytes() + .expect("a created subnet carries a member seed"); // The SAME clock the verifier reads, so the code we present is the code it // expects — a wall-clock skew here would look like a wrong code. let now = spt_net::net::pairing::ntp::ceremony_now_secs(); @@ -154,10 +154,7 @@ fn spawn_broker(home: &Path, spt_bin: &Path) -> (Child, u32, PathBuf) { .env("SPT_HOME", home) // [int->REQ-TEST-DAEMON-EPHEMERAL-ADVISORY-PORTS] This is a co-resident // fleet runner, so advisory well-known ports belong to production. - .env( - spt_daemon::docshost::TEST_EPHEMERAL_ADVISORY_PORTS_ENV, - "1", - ) + .env(spt_daemon::docshost::TEST_EPHEMERAL_ADVISORY_PORTS_ENV, "1") .stdout(Stdio::null()) .stderr(Stdio::from(brain_log_file)) .spawn() @@ -201,7 +198,9 @@ fn spawn_broker(home: &Path, spt_bin: &Path) -> (Child, u32, PathBuf) { /// stage. A tag here would be coverage for a claim this function never makes. fn daemon_diagnostics(home: &Path, brain_log: &Path) -> String { let pre = std::fs::read_to_string(brain_log).unwrap_or_default(); - let sink_path = home.join("logs").join(spt_daemon::stderrlog::STDERR_LOG_BASENAME); + let sink_path = home + .join("logs") + .join(spt_daemon::stderrlog::STDERR_LOG_BASENAME); let sink = std::fs::read_to_string(&sink_path).unwrap_or_default(); // THE HARNESS WITNESS (releases#199), read beside the daemon's own account. // The broker says the launch returned Ok and no session ever registered; this @@ -235,7 +234,9 @@ fn reap(home: &Path, spt_bin: &Path, broker: &mut Child, brain_pid: u32, extra: } let _ = { let mut cmd = Command::new(spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -661,9 +662,15 @@ fn a_loud_launch_failure_is_candidate_a_from_either_witness() { let v = instrument_verdict(&ladder( &["enter", "prepared"], &["received"], - &["ENGINE_ROOM_SPAWN_FAIL:engine-room: broker connect: refused", EXPIRED], + &[ + "ENGINE_ROOM_SPAWN_FAIL:engine-room: broker connect: refused", + EXPIRED, + ], )); - assert!(v.starts_with("A ("), "ENGINE_ROOM_SPAWN_FAIL alone must classify as A: {v}"); + assert!( + v.starts_with("A ("), + "ENGINE_ROOM_SPAWN_FAIL alone must classify as A: {v}" + ); } #[test] @@ -673,34 +680,72 @@ fn a_pty_create_that_never_completed_is_candidate_c() { &["received", "gate_claimed", "pty_creating"], &[EXPIRED], )); - assert!(v.starts_with("C ("), "entered-but-never-completed ConPTY create is C: {v}"); + assert!( + v.starts_with("C ("), + "entered-but-never-completed ConPTY create is C: {v}" + ); } #[test] fn a_row_that_existed_and_then_did_not_is_candidate_d_not_late() { - let spawned = ["received", "gate_claimed", "pty_creating", "pty_created", "row_inserted"]; + let spawned = [ + "received", + "gate_claimed", + "pty_creating", + "pty_created", + "row_inserted", + ]; let mut with_removal = spawned.to_vec(); with_removal.push("row_removed"); - let full_launch = ["enter", "prepared", "connecting", "connected", "requested", "spawned"]; + let full_launch = [ + "enter", + "prepared", + "connecting", + "connected", + "requested", + "spawned", + ]; let v = instrument_verdict(&ladder(&full_launch, &with_removal, &[EXPIRED])); - assert!(v.starts_with("D ("), "an inserted-then-removed row is D: {v}"); + assert!( + v.starts_with("D ("), + "an inserted-then-removed row is D: {v}" + ); // The discriminator: the SAME ladder without the removal is LATE, not D. If // these two collapsed, a harness that died would be reported as one that was // merely slow, which is the reading this whole instrument exists to prevent. let v = instrument_verdict(&ladder(&full_launch, &spawned, &[EXPIRED])); - assert!(v.starts_with("LATE ("), "a row that appeared and stayed is LATE, not D: {v}"); + assert!( + v.starts_with("LATE ("), + "a row that appeared and stayed is LATE, not D: {v}" + ); } #[test] fn a_complete_ladder_with_no_expiry_is_green() { let v = instrument_verdict(&ladder( - &["enter", "prepared", "connecting", "connected", "requested", "spawned"], - &["received", "gate_claimed", "pty_creating", "pty_created", "row_inserted"], + &[ + "enter", + "prepared", + "connecting", + "connected", + "requested", + "spawned", + ], + &[ + "received", + "gate_claimed", + "pty_creating", + "pty_created", + "row_inserted", + ], &["ENGINE_ROOM_BROUGHT_UP:engine-room session=1 adapter=erhost"], )); - assert!(v.starts_with("GREEN ("), "the full ladder with no expiry is green: {v}"); + assert!( + v.starts_with("GREEN ("), + "the full ladder with no expiry is green: {v}" + ); } // The head every verdict carries is the evidence a reader checks the verdict @@ -840,7 +885,14 @@ fn er_bringup_launch_phases_reach_the_sink() { ladder.join("\n"), ); } - for phase in ["enter", "prepared", "connecting", "connected", "requested", "spawned"] { + for phase in [ + "enter", + "prepared", + "connecting", + "connected", + "requested", + "spawned", + ] { assert!( ladder .iter() @@ -937,7 +989,12 @@ fn rc_once(spt_bin: &Path, home: &Path, id: &str, code: &str, stem: &Path) -> Rc .spawn() .expect("spawn spt rc engine-room"); let pid = child.id(); - RcRun { child, pid, out, err } + RcRun { + child, + pid, + out, + err, + } } /// BROKER TRUTH for `id` — the broker's own session table, which is what rc's @@ -1007,7 +1064,6 @@ fn wait_for_session_rotation(perch_path: &Path, prior: &str, budget: Duration) - } } - /// Poll until the daemon's own exit path has normalised the record to offline. /// Returns the row as it finally read — `None`/other means the product did not /// reach the state this arm is about, and the caller must fail rather than @@ -1093,7 +1149,13 @@ fn attempt_bringup_with_status_row(offline_row: bool) -> BringupAttempt { // write the row — the same lifecycle boundary CONTEXT.md ratifies as leaving // the seat "cleanly offline and re-bringable". let row_before: Option = if offline_row { - let warm = rc_once(&spt_bin, home.path(), id, &code, &home.path().join("rc-warm")); + let warm = rc_once( + &spt_bin, + home.path(), + id, + &code, + &home.path().join("rc-warm"), + ); let warm_pid = warm.pid; warm_child = Some(warm.child); let up = wait_for_session(&perch_path, Duration::from_secs(45)); @@ -1149,8 +1211,7 @@ fn attempt_bringup_with_status_row(offline_row: bool) -> BringupAttempt { let truth_after = wait_for_broker_session(id, Duration::from_secs(45)); let spawned = truth_after.is_some(); - let sid_after = - wait_for_session_rotation(&perch_path, &sid_before, Duration::from_secs(10)); + let sid_after = wait_for_session_rotation(&perch_path, &sid_before, Duration::from_secs(10)); let rc_pid = rc.pid; let _ = rc.child.kill(); @@ -1284,7 +1345,10 @@ fn empowerment_sweep() -> Vec<(String, Vec)> { let file = entry.path().join("empowerments.json"); let held = spt_store::empower::Empowerments::load_from(&file); if !held.subnets.is_empty() { - found.push((entry.file_name().to_string_lossy().into_owned(), held.subnets)); + found.push(( + entry.file_name().to_string_lossy().into_owned(), + held.subnets, + )); } } found @@ -1672,7 +1736,11 @@ fn a_bringup_whose_attach_never_arrived_leaves_no_grant_anywhere() { // The second half of the ratified invariant, and it fails independently: an // implementation that announces at admit satisfies "the operator was told" // while leaving the SEAT with nothing to say. - if !seated.seat_note.as_deref().is_some_and(|n| n.contains(&grant)) { + if !seated + .seat_note + .as_deref() + .is_some_and(|n| n.contains(&grant)) + { violations.push(format!( "SEAT CONFIRMED, NOTHING ANNOUNCED ON IT: the seat that redeemed the \ ticket carried no grant sentence for the operator (note={:?}, \ @@ -1773,7 +1841,8 @@ fn a_cleanly_offline_engine_room_is_still_brought_up_by_its_own_gate() { presented a valid code to the seat's own gate, and 'cleanly offline' is \ the state the lifecycle promises is re-bringable, not a wedge.\n\ === rc stdout ===\n{}\n=== rc stderr ===\n{}", - offline.rc_stdout, offline.rc_stderr, + offline.rc_stdout, + offline.rc_stderr, ); assert!( diff --git a/crates/spt/tests/er_brief_once_per_session_e2e.rs b/crates/spt/tests/er_brief_once_per_session_e2e.rs index 36ac5734..98ff2a2e 100644 --- a/crates/spt/tests/er_brief_once_per_session_e2e.rs +++ b/crates/spt/tests/er_brief_once_per_session_e2e.rs @@ -100,7 +100,9 @@ fn seed_subnet_and_code(name: &str) -> String { fn code_for(subnet: &str) -> String { let store = spt_store::subnet::SubnetStore::load(); let rec = store.find(subnet).expect("the subnet seeded by this home"); - let seed = rec.seed_bytes().expect("a created subnet carries a member seed"); + let seed = rec + .seed_bytes() + .expect("a created subnet carries a member seed"); let now = spt_net::net::pairing::ntp::ceremony_now_secs(); spt_net::net::pairing::totp::TotpSeed::from_bytes(seed).code_at(now) } @@ -237,7 +239,9 @@ fn reap(home: &Path, spt_bin: &Path, broker: &mut Child, brain_pid: u32, extra: } let _ = { let mut cmd = Command::new(spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -256,7 +260,9 @@ fn run_ceremony(spt_bin: &Path, home: &Path, subnet: &str, adapter: &str) -> boo for marker in ["OWL_SESSION_ID", "SPT_AGENT_ID", "SPT_ENDPOINT_ID"] { cmd.env_remove(marker); } - common::output_bounded(cmd, Duration::from_secs(30)).status.success() + common::output_bounded(cmd, Duration::from_secs(30)) + .status + .success() } /// Every briefing row the perch holds, delivered or not — the audit read, not a @@ -453,7 +459,10 @@ fn a_second_seat_on_a_running_engine_room_is_not_re_briefed() { === brain stderr ===\n{brain_stderr}" ); - assert!(ceremony_ok, "PRECONDITION: the ceremony must provision the record"); + assert!( + ceremony_ok, + "PRECONDITION: the ceremony must provision the record" + ); // POSITIVE CONTROL — in this same run, before any absence is read. assert_eq!( diff --git a/crates/spt/tests/er_briefing_presentation_e2e.rs b/crates/spt/tests/er_briefing_presentation_e2e.rs index eb44ebd0..e4dbb05f 100644 --- a/crates/spt/tests/er_briefing_presentation_e2e.rs +++ b/crates/spt/tests/er_briefing_presentation_e2e.rs @@ -138,7 +138,9 @@ fn seed_subnet_and_code(name: &str) -> String { let store = spt_store::subnet::SubnetStore::load(); let rec = store.find(name).expect("the subnet we just created"); - let seed = rec.seed_bytes().expect("a created subnet carries a member seed"); + let seed = rec + .seed_bytes() + .expect("a created subnet carries a member seed"); let now = spt_net::net::pairing::ntp::ceremony_now_secs(); spt_net::net::pairing::totp::TotpSeed::from_bytes(seed).code_at(now) } @@ -236,7 +238,9 @@ fn reap(home: &Path, spt_bin: &Path, broker: &mut Child, brain_pid: u32, extra: } let _ = { let mut cmd = Command::new(spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -358,7 +362,10 @@ fn er_briefing_presentation_measurements() { String::from_utf8_lossy(&ceremony.stderr), ); // The one panic before the broker exists — nothing is running yet to strand. - assert!(ceremony_ok, "PRECONDITION: the ceremony must provision the record.\n{ceremony_out}"); + assert!( + ceremony_ok, + "PRECONDITION: the ceremony must provision the record.\n{ceremony_out}" + ); let (mut broker, brain_pid, brain_log) = spawn_broker(home.path(), &spt_bin); let perch_path = perch::resolve_perch_path(id, ParentHint::Infer); @@ -428,7 +435,12 @@ fn er_briefing_presentation_measurements() { // its own load rather than the window. std::thread::sleep(Duration::from_millis(200)); } - (first_reachable_ms, first_er_in_table_ms, unreachable_samples, samples) + ( + first_reachable_ms, + first_er_in_table_ms, + unreachable_samples, + samples, + ) }) }; @@ -446,7 +458,10 @@ fn er_briefing_presentation_measurements() { let a_info_present = info.is_some(); let a_controllable = info.as_ref().and_then(|i| i.controllable); let a_status = info.as_ref().and_then(|i| i.status.clone()); - let session_id = info.as_ref().map(|i| i.session_id.clone()).unwrap_or_default(); + let session_id = info + .as_ref() + .map(|i| i.session_id.clone()) + .unwrap_or_default(); // The three legs of `is_spt_hosted_no_relay`, read one by one so a false // reads as a NAMED leg rather than as an opaque false. This is the predicate // both drive sites and the native arm all gate on, so which leg fails is the @@ -520,7 +535,9 @@ fn er_briefing_presentation_measurements() { let _ = si.write_all(NATIVE_PROBE.as_bytes()); } // stdin dropped → EOF, so `read_stdin` returns and the child exits. - child.wait_with_output().expect("await spt send --force-native") + child + .wait_with_output() + .expect("await spt send --force-native") }; let d_ok = d_send.status.success(); let d_stdout = String::from_utf8_lossy(&d_send.stdout).to_string(); diff --git a/crates/spt/tests/er_briefing_presented_e2e.rs b/crates/spt/tests/er_briefing_presented_e2e.rs index be33a666..f4125b0a 100644 --- a/crates/spt/tests/er_briefing_presented_e2e.rs +++ b/crates/spt/tests/er_briefing_presented_e2e.rs @@ -136,7 +136,9 @@ fn seed_subnet_and_code(name: &str) -> String { store.save().expect("save subnets"); let store = spt_store::subnet::SubnetStore::load(); let rec = store.find(name).expect("the subnet we just created"); - let seed = rec.seed_bytes().expect("a created subnet carries a member seed"); + let seed = rec + .seed_bytes() + .expect("a created subnet carries a member seed"); let now = spt_net::net::pairing::ntp::ceremony_now_secs(); spt_net::net::pairing::totp::TotpSeed::from_bytes(seed).code_at(now) } @@ -255,7 +257,9 @@ fn harness_manifest( fn code_for(subnet: &str) -> String { let store = spt_store::subnet::SubnetStore::load(); let rec = store.find(subnet).expect("the subnet seeded by this home"); - let seed = rec.seed_bytes().expect("a created subnet carries a member seed"); + let seed = rec + .seed_bytes() + .expect("a created subnet carries a member seed"); let now = spt_net::net::pairing::ntp::ceremony_now_secs(); spt_net::net::pairing::totp::TotpSeed::from_bytes(seed).code_at(now) } @@ -351,7 +355,9 @@ fn reap(home: &Path, spt_bin: &Path, broker: &mut Child, brain_pid: u32, extra: } let _ = { let mut cmd = Command::new(spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -370,7 +376,9 @@ fn run_ceremony(spt_bin: &Path, home: &Path, subnet: &str, adapter: &str) -> boo for marker in ["OWL_SESSION_ID", "SPT_AGENT_ID", "SPT_ENDPOINT_ID"] { cmd.env_remove(marker); } - common::output_bounded(cmd, Duration::from_secs(30)).status.success() + common::output_bounded(cmd, Duration::from_secs(30)) + .status + .success() } /// Every retained row with its taker provenance — the audit read, not a count. @@ -403,7 +411,10 @@ fn the_engine_room_briefing_is_presented_before_the_first_actionable_turn() { let code = seed_subnet_and_code(subnet); register_harness(home.path(), &spt_bin, &mock, &xlate, adapter); let ceremony_ok = run_ceremony(&spt_bin, home.path(), subnet, adapter); - assert!(ceremony_ok, "PRECONDITION: the ceremony must provision the record"); + assert!( + ceremony_ok, + "PRECONDITION: the ceremony must provision the record" + ); let (mut broker, brain_pid, brain_log) = spawn_broker(home.path(), &spt_bin); let perch_path = perch::resolve_perch_path(id, ParentHint::Infer); @@ -535,7 +546,10 @@ fn the_engine_room_briefing_is_presented_before_the_first_actionable_turn() { ); // CLAUSE 5, ARM 3 — the never-seated arm. - assert!(ceremony2_ok, "PRECONDITION: the second ceremony must provision the record"); + assert!( + ceremony2_ok, + "PRECONDITION: the second ceremony must provision the record" + ); assert!( unseated_rows.is_empty(), "a provisioned engine room that was never brought up must present nothing — \ @@ -559,7 +573,15 @@ fn the_engine_room_briefing_is_presented_before_the_first_actionable_turn() { // The harness comes up LIVE and never binds (`hold-unbound`). Eligibility // therefore never holds, the drive's bounded poll expires, and the miss is // deterministic without one line of product mutation. - register_harness_mode(home4.path(), &spt_bin, &mock, &xlate, adapter, "hold-unbound", 1000); + register_harness_mode( + home4.path(), + &spt_bin, + &mock, + &xlate, + adapter, + "hold-unbound", + 1000, + ); let ceremony4_ok = run_ceremony(&spt_bin, home4.path(), subnet, adapter); let (mut broker4, brain_pid4, brain_log4) = spawn_broker(home4.path(), &spt_bin); let perch4 = perch::resolve_perch_path(id, ParentHint::Infer); @@ -627,7 +649,14 @@ fn the_engine_room_briefing_is_presented_before_the_first_actionable_turn() { let rc4_pid = rc4.id(); let _ = rc4.kill(); let _ = rc4.wait(); - reap(home4.path(), &spt_bin, &mut broker4, brain_pid4, &[rc4_pid], id); + reap( + home4.path(), + &spt_bin, + &mut broker4, + brain_pid4, + &[rc4_pid], + id, + ); // A stale readiness breadcrumb would hand the next wait the OLD pid and let // the test race a broker that is not up yet. let _ = std::fs::remove_file(home4.path().join("brain.ready")); @@ -675,7 +704,14 @@ fn the_engine_room_briefing_is_presented_before_the_first_actionable_turn() { let rc5_pid = rc5.id(); let _ = rc5.kill(); let _ = rc5.wait(); - reap(home4.path(), &spt_bin, &mut broker5, brain_pid5, &[rc5_pid], id); + reap( + home4.path(), + &spt_bin, + &mut broker5, + brain_pid5, + &[rc5_pid], + id, + ); drop(home4); // ══ VERDICT — arms 4 and 5 ══ @@ -690,7 +726,10 @@ fn the_engine_room_briefing_is_presented_before_the_first_actionable_turn() { === brain stderr ===\n{brain4_stderr}" ); - assert!(ceremony4_ok, "PRECONDITION: the miss arm's ceremony must provision the record"); + assert!( + ceremony4_ok, + "PRECONDITION: the miss arm's ceremony must provision the record" + ); assert_eq!( miss_controllable, None, "PRECONDITION: the unbound harness must leave the perch a NON-eligible inject \ diff --git a/crates/spt/tests/er_briefing_session_scoped_e2e.rs b/crates/spt/tests/er_briefing_session_scoped_e2e.rs index 6de32828..d5f70abf 100644 --- a/crates/spt/tests/er_briefing_session_scoped_e2e.rs +++ b/crates/spt/tests/er_briefing_session_scoped_e2e.rs @@ -92,7 +92,9 @@ fn seed_subnet_and_code(name: &str) -> String { fn code_for(subnet: &str) -> String { let store = spt_store::subnet::SubnetStore::load(); let rec = store.find(subnet).expect("the subnet seeded by this home"); - let seed = rec.seed_bytes().expect("a created subnet carries a member seed"); + let seed = rec + .seed_bytes() + .expect("a created subnet carries a member seed"); let now = spt_net::net::pairing::ntp::ceremony_now_secs(); spt_net::net::pairing::totp::TotpSeed::from_bytes(seed).code_at(now) } @@ -193,7 +195,9 @@ fn reap(home: &Path, spt_bin: &Path, broker: &mut Child, brain_pid: u32, extra: } let _ = { let mut cmd = Command::new(spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -212,7 +216,9 @@ fn run_ceremony(spt_bin: &Path, home: &Path, subnet: &str, adapter: &str) -> boo for marker in ["OWL_SESSION_ID", "SPT_AGENT_ID", "SPT_ENDPOINT_ID"] { cmd.env_remove(marker); } - common::output_bounded(cmd, Duration::from_secs(30)).status.success() + common::output_bounded(cmd, Duration::from_secs(30)) + .status + .success() } /// Every row the perch holds, so a survivor can be NAMED rather than counted. @@ -287,10 +293,7 @@ fn a_new_session_never_delivers_an_older_sessions_briefing() { let mut rows = Vec::new(); while Instant::now() < deadline { rows = briefing_rows(&perch_path); - if rows - .iter() - .any(|r| r.delivered && !planted.contains(&r.id)) - { + if rows.iter().any(|r| r.delivered && !planted.contains(&r.id)) { break; } std::thread::sleep(Duration::from_millis(150)); diff --git a/crates/spt/tests/er_inbound_local.rs b/crates/spt/tests/er_inbound_local.rs index 729ce05b..92abca4a 100644 --- a/crates/spt/tests/er_inbound_local.rs +++ b/crates/spt/tests/er_inbound_local.rs @@ -94,8 +94,11 @@ impl Run { fn make_perch(id: &str) -> PathBuf { let p = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&p).expect("perch dir"); - info::write_info(&p, &InfoJson::new(id, "0", 0, &format!("sid-{id}"), "gateway")) - .expect("write info"); + info::write_info( + &p, + &InfoJson::new(id, "0", 0, &format!("sid-{id}"), "gateway"), + ) + .expect("write info"); p } @@ -133,13 +136,8 @@ fn a_local_send_meets_the_engine_rooms_inbound_lock_on_every_authoring_path() { // everything including the reply arm and make (b) unprovable. let er_perch = make_perch(ENGINE_ROOM_ID); info::set_controlled(&er_perch, true).expect("stamp a controller at the controls"); - engineroom::provision_at( - &perch::engine_room_file(), - "work", - "claude-spt", - 1_000, - ) - .expect("provision the engine room"); + engineroom::provision_at(&perch::engine_room_file(), "work", "claude-spt", 1_000) + .expect("provision the engine room"); assert_eq!( engineroom::posture_now(), engineroom::Posture::Online, @@ -221,7 +219,14 @@ fn a_local_send_meets_the_engine_rooms_inbound_lock_on_every_authoring_path() { // that got past the gate would block for its full window, which is itself a // discriminator (the pre-fix binary would sit here). let f_ring = send( - &["ring", ENGINE_ROOM_ID, "--from", "intruder", "--timeout", "3s"], + &[ + "ring", + ENGINE_ROOM_ID, + "--from", + "intruder", + "--timeout", + "3s", + ], Some("intruder"), "answer me", ); @@ -256,9 +261,14 @@ fn a_local_send_meets_the_engine_rooms_inbound_lock_on_every_authoring_path() { // endpoint. Either way the engine room's own perch must gain nothing. let folded = "Engine-Room"; let folded_perch = perch::resolve_perch_path(folded, ParentHint::Infer); - let folds_case = std::fs::canonicalize(&folded_perch).ok() == std::fs::canonicalize(&er_perch).ok() + let folds_case = std::fs::canonicalize(&folded_perch).ok() + == std::fs::canonicalize(&er_perch).ok() && std::fs::canonicalize(&er_perch).is_ok(); - let e = send(&["send", folded], Some("intruder"), "by the folded spelling"); + let e = send( + &["send", folded], + Some("intruder"), + "by the folded spelling", + ); let rows_after_e = rows(&er_perch); // ── (c) THE HOLE-PUNCH NEGATIVES ───────────────────────────────────────── diff --git a/crates/spt/tests/er_sequestered_cwd_e2e.rs b/crates/spt/tests/er_sequestered_cwd_e2e.rs index 146c8cd5..e5e25fe5 100644 --- a/crates/spt/tests/er_sequestered_cwd_e2e.rs +++ b/crates/spt/tests/er_sequestered_cwd_e2e.rs @@ -115,7 +115,9 @@ fn seed_subnet_and_code(name: &str) -> String { let store = spt_store::subnet::SubnetStore::load(); let rec = store.find(name).expect("the subnet we just created"); - let seed = rec.seed_bytes().expect("a created subnet carries a member seed"); + let seed = rec + .seed_bytes() + .expect("a created subnet carries a member seed"); let now = spt_net::net::pairing::ntp::ceremony_now_secs(); spt_net::net::pairing::totp::TotpSeed::from_bytes(seed).code_at(now) } @@ -237,7 +239,9 @@ fn reap(home: &Path, spt_bin: &Path, broker: &mut Child, brain_pid: u32, extra: } let _ = { let mut cmd = Command::new(spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -305,7 +309,11 @@ fn tree_census(root: &Path) -> Vec { format!("{prefix}/{name}") }; let is_dir = entry.file_type().map(|t| t.is_dir()).unwrap_or(false); - out.push(if is_dir { format!("{rel}/") } else { rel.clone() }); + out.push(if is_dir { + format!("{rel}/") + } else { + rel.clone() + }); if is_dir { walk(&entry.path(), &rel, out); } diff --git a/crates/spt/tests/fixtures/gh_fixture.rs b/crates/spt/tests/fixtures/gh_fixture.rs index 1e6a497f..43d7bd9f 100644 --- a/crates/spt/tests/fixtures/gh_fixture.rs +++ b/crates/spt/tests/fixtures/gh_fixture.rs @@ -35,7 +35,11 @@ fn main() { if let Ok(log) = std::env::var("SPT_FAKE_GH_LOG") { use std::io::Write; - if let Ok(mut f) = std::fs::OpenOptions::new().create(true).append(true).open(&log) { + if let Ok(mut f) = std::fs::OpenOptions::new() + .create(true) + .append(true) + .open(&log) + { let _ = writeln!(f, "gh {}", args.join(" ")); } } diff --git a/crates/spt/tests/fixtures/git_fixture.rs b/crates/spt/tests/fixtures/git_fixture.rs index aedf05c1..b797ebe2 100644 --- a/crates/spt/tests/fixtures/git_fixture.rs +++ b/crates/spt/tests/fixtures/git_fixture.rs @@ -12,7 +12,11 @@ fn main() { let args: Vec = std::env::args().skip(1).collect(); if let Ok(log) = std::env::var("SPT_GIT_SHIM_LOG") { use std::io::Write; - if let Ok(mut f) = std::fs::OpenOptions::new().create(true).append(true).open(&log) { + if let Ok(mut f) = std::fs::OpenOptions::new() + .create(true) + .append(true) + .open(&log) + { let _ = writeln!(f, "git {}", args.join(" ")); } } diff --git a/crates/spt/tests/fork_surface_e2e.rs b/crates/spt/tests/fork_surface_e2e.rs index a6c48c24..9f6cbc03 100644 --- a/crates/spt/tests/fork_surface_e2e.rs +++ b/crates/spt/tests/fork_surface_e2e.rs @@ -115,7 +115,10 @@ fn an_admitted_fork_produces_a_whole_endpoint_and_leaves_the_source_intact() { // The source is untouched: a wire fork copies, it never moves. let src = perch::resolve_perch_path("ling", ParentHint::Infer); - assert!(spt_store::info::read_info(&src).is_some(), "source perch gone"); + assert!( + spt_store::info::read_info(&src).is_some(), + "source perch gone" + ); assert!( tracked.join("agents").join("ling").exists(), "the source's mind must survive a fork of it" diff --git a/crates/spt/tests/gateway_e2e.rs b/crates/spt/tests/gateway_e2e.rs index 6d12d97a..ee8ebf27 100644 --- a/crates/spt/tests/gateway_e2e.rs +++ b/crates/spt/tests/gateway_e2e.rs @@ -34,8 +34,6 @@ use spt_store::spool; /// Serialize the process-global `SPT_HOME` mutation across tests in this binary. static E2E_LOCK: Mutex<()> = Mutex::new(()); - - fn keys(pairs: &[(&str, &str)]) -> std::collections::BTreeMap { pairs .iter() @@ -64,7 +62,8 @@ fn start_inproc_daemon() { fn offline_peer(id: &str) -> PathBuf { let perch_path = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&perch_path).unwrap(); - let rec = spt_store::info::InfoJson::new(id, "now", std::process::id(), "peer-sess", "ready_agent"); + let rec = + spt_store::info::InfoJson::new(id, "now", std::process::id(), "peer-sess", "ready_agent"); spt_store::info::write_info(&perch_path, &rec).unwrap(); perch_path } @@ -95,7 +94,11 @@ fn send_user_msg( .unwrap() .write_all(body.as_bytes()) .unwrap(); - child.wait_with_output().expect("send output").status.success() + child + .wait_with_output() + .expect("send output") + .status + .success() } /// The single spooled body for `perch_path` (oldest), or panic. @@ -116,7 +119,11 @@ fn gateway_binds_and_is_the_user_backed_origin() { let spt_bin = PathBuf::from(env!("CARGO_BIN_EXE_spt")); let mock_bin = common::sibling_bin("mock-session"); - assert!(mock_bin.exists(), "mock-session must be built: {}", mock_bin.display()); + assert!( + mock_bin.exists(), + "mock-session must be built: {}", + mock_bin.display() + ); // Load the mock-gateway manifest; point [session.self] at the built binaries. let manifest_path = concat!( @@ -161,7 +168,10 @@ fn gateway_binds_and_is_the_user_backed_origin() { let gw_perch = perch::resolve_perch_path(gw, ParentHint::Infer); let rec = spt_store::info::read_info(&gw_perch).expect("gateway info.json after bind"); assert_eq!(rec.session_id, gw_session); - assert_eq!(rec.state, "gateway", "a Gateway binds with its open-type tag"); + assert_eq!( + rec.state, "gateway", + "a Gateway binds with its open-type tag" + ); // 2. A user-msg SENT FROM the gateway is HONORED (the user-backed origin): // the peer's spool carries a verbatim user-msg envelope. @@ -209,7 +219,14 @@ fn gateway_binds_and_is_the_user_backed_origin() { let peer_a = "peer-of-agent"; let peer_a_perch = offline_peer(peer_a); assert!( - send_user_msg(&spt_bin, home.path(), peer_a, agent, agent_session, "do this"), + send_user_msg( + &spt_bin, + home.path(), + peer_a, + agent, + agent_session, + "do this" + ), "send from the agent succeeds (degraded, never rejected)" ); let body = spooled_body(&peer_a_perch); diff --git a/crates/spt/tests/gateway_owner_shell_e2e.rs b/crates/spt/tests/gateway_owner_shell_e2e.rs index 2cf1e0c9..82178575 100644 --- a/crates/spt/tests/gateway_owner_shell_e2e.rs +++ b/crates/spt/tests/gateway_owner_shell_e2e.rs @@ -90,8 +90,9 @@ fn start_inproc_daemon(dir: &std::path::Path) { }); let host = NetHost::start(hermetic(Identity::generate())).expect("net host start"); - let broker = Broker::bind_in_with_net(&broker_socket_name(), dir.join("effects.log"), Some(host)) - .expect("bind broker with net"); + let broker = + Broker::bind_in_with_net(&broker_socket_name(), dir.join("effects.log"), Some(host)) + .expect("bind broker with net"); let serve = Arc::clone(&broker); thread::spawn(move || { let _ = serve.serve(); @@ -120,7 +121,9 @@ fn start_inproc_daemon(dir: &std::path::Path) { /// Spawn `cmd` with `input` on stdin, capture output, bounded. fn output_with_stdin(mut cmd: Command, input: Vec, deadline: Duration) -> Output { - cmd.stdin(Stdio::piped()).stdout(Stdio::piped()).stderr(Stdio::piped()); + cmd.stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); let (tx, rx) = std::sync::mpsc::channel(); thread::spawn(move || { let res = (|| { @@ -198,15 +201,29 @@ fn gateway_typed_owner_owns_a_shell_on_every_path_keyed_on_id() { spt_store::nodeid::load_or_create().expect("node identity"); let rec = spt_store::info::read_info(&perch::resolve_perch_path(gw_a, ParentHint::Infer)) .expect("owner info"); - assert_eq!(rec.state, "gateway", "the owner is a Gateway-typed endpoint, not an agent"); + assert_eq!( + rec.state, "gateway", + "the owner is a Gateway-typed endpoint, not an agent" + ); let owlery = perch::owlery_dir(); let shell_perch = perch::resolve_shell_perch_path_in(&owlery, gw_a, "mock-shell-0"); let token_of = || spt_daemon::shellhost::read_link_token(&shell_perch).expect("a link token is parked"); let online_by_token = |token: &str| { - let out = spt(&["api", "--adapter", "mock-shell", "bind-shell", "--link", token]); - assert!(out.status.success(), "bind-shell: {}", String::from_utf8_lossy(&out.stderr)); + let out = spt(&[ + "api", + "--adapter", + "mock-shell", + "bind-shell", + "--link", + token, + ]); + assert!( + out.status.success(), + "bind-shell: {}", + String::from_utf8_lossy(&out.stderr) + ); assert!( String::from_utf8_lossy(&out.stderr).contains("SHELL_TUNNEL_OPEN"), "bind-shell opens the tunnel for a Gateway owner too: {}", @@ -215,8 +232,20 @@ fn gateway_typed_owner_owns_a_shell_on_every_path_keyed_on_id() { }; // ── spawn (offline) under the GATEWAY owner → online by token → tunnel opens. - let out = spt(&["shell", "spawn", "mock-shell", "--alias", "Scout", "--owner", gw_a]); - assert!(out.status.success(), "gateway spawn: {}", String::from_utf8_lossy(&out.stderr)); + let out = spt(&[ + "shell", + "spawn", + "mock-shell", + "--alias", + "Scout", + "--owner", + gw_a, + ]); + assert!( + out.status.success(), + "gateway spawn: {}", + String::from_utf8_lossy(&out.stderr) + ); let token_a = token_of(); // FIXTURE INTENT (REQ-HAZARD-SHELL-STALE-ONLINE): the suite models a LIVE // linked binary — the test process drains the link via `api drive-poll` / @@ -236,7 +265,11 @@ fn gateway_typed_owner_owns_a_shell_on_every_path_keyed_on_id() { // durable shell channel — no agent-family gate on the command path. let before = spt_store::spool::pending_count_at(&shell_perch).unwrap(); let out = spt(&["shell", "cmd", "--owner", gw_a, "Scout", "press", "A"]); - assert!(out.status.success(), "gateway cmd: {}", String::from_utf8_lossy(&out.stderr)); + assert!( + out.status.success(), + "gateway cmd: {}", + String::from_utf8_lossy(&out.stderr) + ); assert_eq!( spt_store::spool::pending_count_at(&shell_perch).unwrap(), before + 1, @@ -252,7 +285,13 @@ fn gateway_typed_owner_owns_a_shell_on_every_path_keyed_on_id() { "gateway drive" ); let out = spt(&[ - "api", "--adapter", "mock-shell", "drive-poll", "mock-shell-0", "--link", &token_a, + "api", + "--adapter", + "mock-shell", + "drive-poll", + "mock-shell-0", + "--link", + &token_a, ]); let frame = String::from_utf8_lossy(&out.stdout); assert!( @@ -263,15 +302,27 @@ fn gateway_typed_owner_owns_a_shell_on_every_path_keyed_on_id() { // ── tunnel: opaque bytes round-trip BOTH directions under the gateway owner. // A payload the grammar would mangle (NULs + an `| { - let out = - spt_stdin(&["shell", "tunnel", "Scout", "send", "--owner", gw_a], bytes); - assert!(out.status.success(), "gateway tunnel send: {}", String::from_utf8_lossy(&out.stderr)); + let out = spt_stdin( + &["shell", "tunnel", "Scout", "send", "--owner", gw_a], + bytes, + ); + assert!( + out.status.success(), + "gateway tunnel send: {}", + String::from_utf8_lossy(&out.stderr) + ); }; let shell_recv_until = |want: usize| -> Vec { let mut got = Vec::new(); for _ in 0..400 { let out = spt(&[ - "api", "--adapter", "mock-shell", "tunnel", "mock-shell-0", "recv", "--link", + "api", + "--adapter", + "mock-shell", + "tunnel", + "mock-shell-0", + "recv", + "--link", &token_a, ]); got.extend_from_slice(&out.stdout); @@ -297,29 +348,67 @@ fn gateway_typed_owner_owns_a_shell_on_every_path_keyed_on_id() { let blob: Vec = b"\x00opaque\xff\xfe\x00".to_vec(); owner_send(blob.clone()); let got = shell_recv_until(blob.len()); - assert_eq!(got, blob, "owner→shell opaque bytes round-trip byte-exact under a gateway owner"); + assert_eq!( + got, blob, + "owner→shell opaque bytes round-trip byte-exact under a gateway owner" + ); let reply: Vec = b"\x00\x01\xaa reply".to_vec(); let out = spt_stdin( - &["api", "--adapter", "mock-shell", "tunnel", "mock-shell-0", "send", "--link", &token_a], + &[ + "api", + "--adapter", + "mock-shell", + "tunnel", + "mock-shell-0", + "send", + "--link", + &token_a, + ], reply.clone(), ); - assert!(out.status.success(), "shell tunnel send: {}", String::from_utf8_lossy(&out.stderr)); - assert_eq!(owner_recv_until(reply.len()), reply, "shell→owner round-trip byte-exact"); + assert!( + out.status.success(), + "shell tunnel send: {}", + String::from_utf8_lossy(&out.stderr) + ); + assert_eq!( + owner_recv_until(reply.len()), + reply, + "shell→owner round-trip byte-exact" + ); // ── act-gate (REQ-CONSENT-3): the class-keyed `attach` refuses ungranted, // then a grant KEYED ON THE GATEWAY'S ENDPOINT-ID flips it through — the // same id-not-type invariant on the consent surface. - let out = spt(&["shell", "cmd", "--owner", gw_a, "Scout", "attach", "busid-1"]); - assert!(!out.status.success(), "ungranted gated attach refuses under the gateway"); + let out = spt(&[ + "shell", "cmd", "--owner", gw_a, "Scout", "attach", "busid-1", + ]); + assert!( + !out.status.success(), + "ungranted gated attach refuses under the gateway" + ); assert!( String::from_utf8_lossy(&out.stderr).contains("CONSENT_PENDING"), "refused as a pending act-gate: {}", String::from_utf8_lossy(&out.stderr) ); // The grant target IS the gateway's endpoint-id (not a type, not an agent id). - let out = spt(&["grant", "add", "shell-act:attach", gw_a, "--qualifier", "hid"]); - assert!(out.status.success(), "grant add: {}", String::from_utf8_lossy(&out.stderr)); - let out = spt(&["shell", "cmd", "--owner", gw_a, "Scout", "attach", "busid-1"]); + let out = spt(&[ + "grant", + "add", + "shell-act:attach", + gw_a, + "--qualifier", + "hid", + ]); + assert!( + out.status.success(), + "grant add: {}", + String::from_utf8_lossy(&out.stderr) + ); + let out = spt(&[ + "shell", "cmd", "--owner", gw_a, "Scout", "attach", "busid-1", + ]); assert!( out.status.success(), "the grant keyed on the gateway endpoint-id flips the gated cmd through: {}", @@ -336,8 +425,16 @@ fn gateway_typed_owner_owns_a_shell_on_every_path_keyed_on_id() { spt_daemon::shellhost::close_shell(&owlery, gw_a, "mock-shell-0", Some(&shell)) .expect("link break closes the gateway-owned shell"); let out = spt(&["shell", "relink", "Scout", "--owner", gw_a]); - assert!(out.status.success(), "gateway relink: {}", String::from_utf8_lossy(&out.stderr)); - assert_ne!(token_a, token_of(), "relink rotates the link token for a gateway owner"); + assert!( + out.status.success(), + "gateway relink: {}", + String::from_utf8_lossy(&out.stderr) + ); + assert_ne!( + token_a, + token_of(), + "relink rotates the link token for a gateway owner" + ); // ── NEGATIVE: gateway-B (SAME type="gateway", DIFFERENT id) is refused on // every control path for gateway-A's shell — exclusivity keys on the owner @@ -351,7 +448,9 @@ fn gateway_typed_owner_owns_a_shell_on_every_path_keyed_on_id() { "same-type different-id owner: cmd is NO_SHELL: {}", String::from_utf8_lossy(&out.stderr) ); - let out = spt(&["shell", "drive", "Scout", "--type", "stick", "x=0.1", "--owner", gw_b]); + let out = spt(&[ + "shell", "drive", "Scout", "--type", "stick", "x=0.1", "--owner", gw_b, + ]); assert!(!out.status.success(), "gateway-B drive refused"); assert!( String::from_utf8_lossy(&out.stderr).contains("NO_SHELL"), diff --git a/crates/spt/tests/hide_new_remote_rows_e2e.rs b/crates/spt/tests/hide_new_remote_rows_e2e.rs index 14f0f584..f2b6a353 100644 --- a/crates/spt/tests/hide_new_remote_rows_e2e.rs +++ b/crates/spt/tests/hide_new_remote_rows_e2e.rs @@ -46,8 +46,6 @@ use spt_store::info::{self, InfoJson}; use spt_store::perch::{self, ParentHint}; use spt_store::subnet::SubnetStore; - - fn instance_on(node: &str) -> Instance { Instance { node: node.to_string(), @@ -102,7 +100,10 @@ fn hide_new_keeps_our_own_endpoint_hidden_and_leaves_other_nodes_rows_alone() { .public_key() .to_hex(); let remote_node = "11".repeat(32); - assert_ne!(self_node, remote_node, "the fixture's two nodes are distinct"); + assert_ne!( + self_node, remote_node, + "the fixture's two nodes are distinct" + ); // ── This node's OWN endpoint: a real perch, so the roster (which is what // the listing hands `Exclusions::owning`) genuinely owns it. It carries @@ -116,7 +117,9 @@ fn hide_new_keeps_our_own_endpoint_hidden_and_leaves_other_nodes_rows_alone() { // ── The subnet, with the posture the defect needs ── let subnet_file = perch::subnet_file(); let mut subnets = SubnetStore::load_from(&subnet_file); - subnets.create_subnet(subnet, Mode::Open).expect("create subnet"); + subnets + .create_subnet(subnet, Mode::Open) + .expect("create subnet"); subnets .set_hide_new_endpoints(subnet, true) .expect("arm hide_new"); @@ -132,8 +135,11 @@ fn hide_new_keeps_our_own_endpoint_hidden_and_leaves_other_nodes_rows_alone() { reg.merge_instance(mine, instance_on(&self_node)); reg.merge_instance(theirs, instance_on(&remote_node)); let write_snapshot = |reg: &SubnetRegistry| { - std::fs::write(&snapshot, serde_json::to_string(reg).expect("encode registry")) - .expect("write snapshot") + std::fs::write( + &snapshot, + serde_json::to_string(reg).expect("encode registry"), + ) + .expect("write snapshot") }; write_snapshot(®); @@ -149,7 +155,10 @@ fn hide_new_keeps_our_own_endpoint_hidden_and_leaves_other_nodes_rows_alone() { .args(["endpoint", "list", "--json"]) .env("SPT_HOME", home.path()); let out = common::output_bounded(cmd, Duration::from_secs(30)); - assert!(out.status.success(), "endpoint list --json must succeed: {out:?}"); + assert!( + out.status.success(), + "endpoint list --json must succeed: {out:?}" + ); let text = String::from_utf8_lossy(&out.stdout).to_string(); eprintln!("=== endpoint list --json ===\n{text}"); serde_json::from_str::(&text).expect("valid JSON listing") diff --git a/crates/spt/tests/human_redeem_msg_code_e2e.rs b/crates/spt/tests/human_redeem_msg_code_e2e.rs index 27a176ec..8055c8a0 100644 --- a/crates/spt/tests/human_redeem_msg_code_e2e.rs +++ b/crates/spt/tests/human_redeem_msg_code_e2e.rs @@ -36,13 +36,13 @@ use std::time::Duration; mod common; use common::CommandNoWindowExt; -use spt_store::access::{AccessRequest, AccessStore, MatchedTier, OriginClass, OriginQualifier, Subject}; +use spt_store::access::{ + AccessRequest, AccessStore, MatchedTier, OriginClass, OriginQualifier, Subject, +}; use spt_store::info::{self, InfoJson, PidValue}; use spt_store::knock::{CodeForm, Directionality, KnockCode, KnockStore, TargetTier}; use spt_store::perch::{self, ParentHint}; - - /// A child with NO identity markers — the bare-terminal presenter class. /// /// This is the fixture's whole instrument. `resolve_knocker` walks @@ -260,7 +260,9 @@ fn a_bare_terminal_redeeming_an_acknowledgmentless_msg_code_reaches_a_decision() // The acknowledgment nobody gave. admit_node: false, }); - knocks.save_to(&perch::knocks_file()).expect("seed the xfer code"); + knocks + .save_to(&perch::knocks_file()) + .expect("seed the xfer code"); let mut cmd = Command::new(&spt_bin); bare_terminal(&mut cmd) diff --git a/crates/spt/tests/idle_edge_drain_e2e.rs b/crates/spt/tests/idle_edge_drain_e2e.rs index 4542fbc3..1ded7aaf 100644 --- a/crates/spt/tests/idle_edge_drain_e2e.rs +++ b/crates/spt/tests/idle_edge_drain_e2e.rs @@ -68,8 +68,6 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - // [int->REQ-MSG-IDLE-EDGE-DRAIN] // [int->REQ-HAZARD-DELIVERY-STARVATION] // [int->REQ-SEND-WINDOW-DRAIN-HONOR] @@ -89,8 +87,16 @@ fn spool_while_active_then_idle_fires_injection() { .unwrap_or_default(); let mock_session = common::sibling_bin("mock-session"); let xlate_fixture = common::sibling_bin("translate_proof_fixture"); - assert!(mock_session.exists(), "dummy-harness must be built: {}", mock_session.display()); - assert!(xlate_fixture.exists(), "translation fixture must be built: {}", xlate_fixture.display()); + assert!( + mock_session.exists(), + "dummy-harness must be built: {}", + mock_session.display() + ); + assert!( + xlate_fixture.exists(), + "translation fixture must be built: {}", + xlate_fixture.display() + ); // ── (2) Register adapter `cc`: a long-lived dummy-harness `[session.self]` + // the REAL `translate_proof_fixture` as the idle-translation binary (choreo @@ -133,18 +139,20 @@ fn spool_while_active_then_idle_fires_injection() { .stderr(Stdio::from(brain_log_file)) .spawn() .expect("spawn spt daemon run (broker process)"); - let brain_pid = - match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(120)) { - Some(p) => p, - None => { - let _ = broker.kill(); - let _ = broker.wait(); - panic!( + let brain_pid = match wait_for_ready_pid( + &home.path().join("brain.ready"), + Duration::from_secs(120), + ) { + Some(p) => p, + None => { + let _ = broker.kill(); + let _ = broker.wait(); + panic!( "PRECONDITION: brain.ready not observed within the 120s budget (the brain may well be up - read the captured stderr below; BRAIN_PHASE lines time the ready path).\n{}", common::daemon_stderr_panel(&brain_log) ); - } - }; + } + }; // ── (4) `endpoint create idleedge --adapter cc` + `endpoint start idleedge`: // the broker spawns the @@ -188,7 +196,10 @@ fn spool_while_active_then_idle_fires_injection() { let mut rec = spt_store::info::read_info(&self_perch) .expect("the online endpoint must have an info.json"); let session_id = rec.session_id.clone(); - assert!(!session_id.is_empty(), "the bound harness must have stamped a session_id"); + assert!( + !session_id.is_empty(), + "the bound harness must have stamped a session_id" + ); if rec.controllable != Some(true) { rec.controllable = Some(true); spt_store::info::write_info(&self_perch, &rec).expect("stamp controllable=true"); @@ -276,7 +287,9 @@ fn spool_while_active_then_idle_fires_injection() { } let _ = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -284,7 +297,10 @@ fn spool_while_active_then_idle_fires_injection() { let _ = broker.wait(); // ── ASSERTIONS ── - assert!(run.status.success(), "endpoint start must succeed: {run_stderr}"); + assert!( + run.status.success(), + "endpoint start must succeed: {run_stderr}" + ); assert!( online, "PRECONDITION: the cc endpoint must bind ONLINE before the idle edge.\n\ diff --git a/crates/spt/tests/idle_edge_seal_e2e.rs b/crates/spt/tests/idle_edge_seal_e2e.rs index 82e4b5c9..a022e049 100644 --- a/crates/spt/tests/idle_edge_seal_e2e.rs +++ b/crates/spt/tests/idle_edge_seal_e2e.rs @@ -72,8 +72,6 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - /// The trailing turn of a `spt endpoint digest --json` document, as /// `(partial, input_seq, entry_seqs)` — the exact triple a seq-keyed scanner reads. fn trailing(doc: &serde_json::Value) -> (bool, Option, Vec>) { @@ -84,7 +82,10 @@ fn trailing(doc: &serde_json::Value) -> (bool, Option, Vec>) { let last = turns .last() .unwrap_or_else(|| panic!("the digest must carry at least one turn: {doc}")); - let partial = last.get("partial").and_then(|p| p.as_bool()).unwrap_or(false); + let partial = last + .get("partial") + .and_then(|p| p.as_bool()) + .unwrap_or(false); let input_seq = last.get("input_seq").and_then(|s| s.as_u64()); // `DigestEntry` is an externally-tagged enum, so an entry is // `{"Agent": {"text": …, "seq": 1}}` — reach through the variant wrapper. `seq` @@ -165,18 +166,20 @@ fn idle_seals_the_latest_turn_with_a_stable_seq_and_no_further_prompt() { .stderr(Stdio::from(brain_log_file)) .spawn() .expect("spawn spt daemon run (broker process)"); - let brain_pid = - match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(120)) { - Some(p) => p, - None => { - let _ = broker.kill(); - let _ = broker.wait(); - panic!( + let brain_pid = match wait_for_ready_pid( + &home.path().join("brain.ready"), + Duration::from_secs(120), + ) { + Some(p) => p, + None => { + let _ = broker.kill(); + let _ = broker.wait(); + panic!( "PRECONDITION: brain.ready not observed within the 120s budget (the brain may well be up - read the captured stderr below; BRAIN_PHASE lines time the ready path).\n{}", common::daemon_stderr_panel(&brain_log) ); - } - }; + } + }; // ── (4) `endpoint create idleseal --adapter cc` + `endpoint start idleseal`, // wait for ONLINE. ── @@ -323,7 +326,9 @@ fn idle_seals_the_latest_turn_with_a_stable_seq_and_no_further_prompt() { } let _ = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -331,12 +336,18 @@ fn idle_seals_the_latest_turn_with_a_stable_seq_and_no_further_prompt() { let _ = broker.wait(); // ── PRECONDITIONS ── - assert!(run.status.success(), "endpoint start must succeed: {run_stderr}"); + assert!( + run.status.success(), + "endpoint start must succeed: {run_stderr}" + ); assert!( online, "PRECONDITION: the cc endpoint must bind ONLINE.\n{brain_stderr}" ); - assert!(!session_id.is_empty(), "PRECONDITION: the harness must stamp a session_id"); + assert!( + !session_id.is_empty(), + "PRECONDITION: the harness must stamp a session_id" + ); for (what, out) in [ ("input", &entry_input), ("agent", &entry_agent), @@ -382,8 +393,15 @@ fn idle_seals_the_latest_turn_with_a_stable_seq_and_no_further_prompt() { seq is the whole thing a seq-keyed scanner reads", ); // Log-less sink: the seq IS the append-only line index (line 0 = the input). - assert_eq!(seq, 0, "the sealed seq is the source log position, not a window index"); - assert_eq!(entry_seqs, vec![Some(1)], "the agent reply seals at its own line index"); + assert_eq!( + seq, 0, + "the sealed seq is the source log position, not a window index" + ); + assert_eq!( + entry_seqs, + vec![Some(1)], + "the agent reply seals at its own line index" + ); assert_eq!( repull, sealed, "a re-pull of an unchanged idle endpoint must return the IDENTICAL seq — a \ @@ -393,9 +411,7 @@ fn idle_seals_the_latest_turn_with_a_stable_seq_and_no_further_prompt() { // ── LEG 3: THE BLINK. The seal is stateless, so the middle read may unseal — // but the RESEAL must reproduce byte-identical seqs (doyle's ruled grounds: // seqs are computed from log position, not from when the seal ran). ── - eprintln!( - "BLINK OBSERVED: sealed={sealed:?} -> busy={blink_busy:?} -> resealed={resealed:?}" - ); + eprintln!("BLINK OBSERVED: sealed={sealed:?} -> busy={blink_busy:?} -> resealed={resealed:?}"); assert_eq!( resealed, sealed, "REQ-DIGEST-SEAL-ON-IDLE / doyle blink ruling: an idle->busy->idle round trip \ @@ -409,7 +425,10 @@ fn idle_seals_the_latest_turn_with_a_stable_seq_and_no_further_prompt() { // ── LEG 4: THE STRAGGLER. A post-seal record folds in; published seqs hold. ── let (late_partial, late_input_seq, late_entry_seqs) = straggled.clone(); - assert!(!late_partial, "the endpoint is still idle — the turn stays sealed"); + assert!( + !late_partial, + "the endpoint is still idle — the turn stays sealed" + ); assert_eq!( late_input_seq, Some(seq), diff --git a/crates/spt/tests/intra_node_degrade.rs b/crates/spt/tests/intra_node_degrade.rs index ad9231fb..3bb6ef04 100644 --- a/crates/spt/tests/intra_node_degrade.rs +++ b/crates/spt/tests/intra_node_degrade.rs @@ -44,8 +44,11 @@ use spt_store::perch::{self, ParentHint}; fn make_perch(id: &str) -> PathBuf { let p = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&p).expect("perch dir"); - info::write_info(&p, &InfoJson::new(id, "0", 0, &format!("sid-{id}"), "gateway")) - .expect("write info"); + info::write_info( + &p, + &InfoJson::new(id, "0", 0, &format!("sid-{id}"), "gateway"), + ) + .expect("write info"); p } diff --git a/crates/spt/tests/intra_node_self.rs b/crates/spt/tests/intra_node_self.rs index 91c78404..15316f42 100644 --- a/crates/spt/tests/intra_node_self.rs +++ b/crates/spt/tests/intra_node_self.rs @@ -115,8 +115,11 @@ impl Run { fn make_perch(id: &str) -> PathBuf { let p = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&p).expect("perch dir"); - info::write_info(&p, &InfoJson::new(id, "0", 0, &format!("sid-{id}"), "gateway")) - .expect("write info"); + info::write_info( + &p, + &InfoJson::new(id, "0", 0, &format!("sid-{id}"), "gateway"), + ) + .expect("write info"); p } diff --git a/crates/spt/tests/io_events_poll_e2e.rs b/crates/spt/tests/io_events_poll_e2e.rs index f0a76719..226ea2c3 100644 --- a/crates/spt/tests/io_events_poll_e2e.rs +++ b/crates/spt/tests/io_events_poll_e2e.rs @@ -72,7 +72,15 @@ fn manifest_with_io(home: &Path) -> PathBuf { } /// Fire one real ingest edge, which is what publishes to the funnel. -fn ingest(spt_bin: &Path, home: &Path, manifest: &Path, id: &str, sid: &str, state: &str, body: &str) { +fn ingest( + spt_bin: &Path, + home: &Path, + manifest: &Path, + id: &str, + sid: &str, + state: &str, + body: &str, +) { let payload = home.join(format!("turn-{state}-{}.txt", body.len())); std::fs::write(&payload, body).unwrap(); let mut cmd = Command::new(spt_bin); @@ -115,7 +123,8 @@ fn poll(spt_bin: &Path, home: &Path, id: &str, sid: &str, extra: &[&str]) -> ser String::from_utf8_lossy(&out.stderr) ); let text = String::from_utf8_lossy(&out.stdout).to_string(); - serde_json::from_str(&text).unwrap_or_else(|e| panic!("poll output is not JSON ({e}): {text:?}")) + serde_json::from_str(&text) + .unwrap_or_else(|e| panic!("poll output is not JSON ({e}): {text:?}")) } fn kinds(v: &serde_json::Value) -> Vec { @@ -159,27 +168,40 @@ fn a_fresh_session_seeds_over_real_history_and_then_sees_only_what_follows() { let perch_path = perch::resolve_perch_path(author, ParentHint::Infer); std::fs::create_dir_all(&perch_path).unwrap(); - let rec = spt_store::info::InfoJson::new( - author, - "0", - std::process::id(), - sid, - "live_agent", - ); + let rec = spt_store::info::InfoJson::new(author, "0", std::process::id(), sid, "live_agent"); spt_store::info::write_info(&perch_path, &rec).unwrap(); let manifest = manifest_with_io(home.path()); let body = std::panic::catch_unwind(|| { // ── HISTORY, before any adapter has ever polled. Two real ingest edges. - ingest(&spt_bin, home.path(), &manifest, author, sid, "busy", "ancient question"); - ingest(&spt_bin, home.path(), &manifest, author, sid, "idle", "ancient answer"); + ingest( + &spt_bin, + home.path(), + &manifest, + author, + sid, + "busy", + "ancient question", + ); + ingest( + &spt_bin, + home.path(), + &manifest, + author, + sid, + "idle", + "ancient answer", + ); // ── (1)+(2) THE SEED, over a log that is NOT empty. The non-zero cursor // is what proves the sink ran: an unregistered sink, a broken append // or a store that never got written would seed at 0 and this test // would be the vacuous green it exists to refuse. let first = poll(&spt_bin, home.path(), author, sid, &[]); - assert_eq!(first["seeded"], true, "a session with no cursor SEEDS: {first}"); + assert_eq!( + first["seeded"], true, + "a session with no cursor SEEDS: {first}" + ); assert_eq!( kinds(&first).len(), 0, @@ -195,9 +217,20 @@ fn a_fresh_session_seeds_over_real_history_and_then_sees_only_what_follows() { ); // ── (3) Something happens, and the SAME session polls again. - ingest(&spt_bin, home.path(), &manifest, author, sid, "busy", "fresh question"); + ingest( + &spt_bin, + home.path(), + &manifest, + author, + sid, + "busy", + "fresh question", + ); let second = poll(&spt_bin, home.path(), author, sid, &[]); - assert_eq!(second["seeded"], false, "an established session never re-seeds"); + assert_eq!( + second["seeded"], false, + "an established session never re-seeds" + ); assert_eq!( payloads(&second), vec!["fresh question".to_string()], @@ -250,6 +283,20 @@ fn a_fresh_session_seeds_over_real_history_and_then_sees_only_what_follows() { "TOOL_USE has no emitter and this verb does not invent one: {whole}" ); + // [int->REQ-IO-EVENT-POLL-VERB] An oversized cursor must not echo + // itself forever while a non-empty log sits below it. + let head = whole["cursor"].as_u64().expect("log head"); + let above_head = (head + 1).to_string(); + let beyond = poll( + &spt_bin, + home.path(), + author, + sid, + &["--after", &above_head], + ); + assert!(kinds(&beyond).is_empty(), "{beyond}"); + assert_eq!(beyond["cursor"].as_u64(), Some(head), "{beyond}"); + // ── (6) The explicit cursor wrote no session state to collide with the // hook's own — the session cursor is exactly where (4) left it. let after_whole = poll(&spt_bin, home.path(), author, sid, &[]); @@ -266,7 +313,14 @@ fn a_fresh_session_seeds_over_real_history_and_then_sees_only_what_follows() { // answer — the log is demonstrably full by this point. let mut bare = Command::new(&spt_bin); bare.no_window() - .args(["--json", "api", "io-events", author, "--token", "not-a-real-token"]) + .args([ + "--json", + "api", + "io-events", + author, + "--token", + "not-a-real-token", + ]) .env("SPT_HOME", home.path()); let out = common::output_bounded(bare, Duration::from_secs(60)); assert!( diff --git a/crates/spt/tests/io_events_undriven_kinds_e2e.rs b/crates/spt/tests/io_events_undriven_kinds_e2e.rs index 5f23372e..5064bf06 100644 --- a/crates/spt/tests/io_events_undriven_kinds_e2e.rs +++ b/crates/spt/tests/io_events_undriven_kinds_e2e.rs @@ -267,8 +267,8 @@ impl Rig { } fn reap(&self, label: &str) { - let observed = reap::breadcrumb_daemon_pid(self.home.path()) - .and_then(|pid| reap::observe(label, pid)); + let observed = + reap::breadcrumb_daemon_pid(self.home.path()).and_then(|pid| reap::observe(label, pid)); let mut stop = Command::new(&self.spt_bin); stop.no_window() .args(["daemon", "stop"]) @@ -309,7 +309,11 @@ fn a_consumed_commune_reaches_the_log_and_polls_back() { .expect("live host"); std::fs::write(r.drop_path(), COMMUNE_BODY).unwrap(); let report = host.pulse_tick(Some(SID_A)).expect("tick"); - assert_eq!(report.ingested.len(), 1, "PRECONDITION: the drop was ingested"); + assert_eq!( + report.ingested.len(), + 1, + "PRECONDITION: the drop was ingested" + ); assert!( !r.drop_path().exists(), "PRECONDITION: a consumed drop is unlinked, which is why the event must carry its bytes" diff --git a/crates/spt/tests/io_state_payload_e2e.rs b/crates/spt/tests/io_state_payload_e2e.rs index bd15912c..e55fe9c6 100644 --- a/crates/spt/tests/io_state_payload_e2e.rs +++ b/crates/spt/tests/io_state_payload_e2e.rs @@ -119,7 +119,13 @@ fn a_payload_carrying_state_call_spools_a_durable_io_frame() { // ── spawn: the noop exits, the perch stays offline, a link token parks. let out = spt(&[ - "shell", "spawn", "mock-shell", "--alias", "Scout", "--owner", owner, + "shell", + "spawn", + "mock-shell", + "--alias", + "Scout", + "--owner", + owner, ]); assert!( out.status.success(), @@ -129,7 +135,8 @@ fn a_payload_carrying_state_call_spools_a_durable_io_frame() { let owlery = perch::owlery_dir(); let shell_id = "mock-shell-0"; let shell_perch = perch::resolve_shell_perch_path_in(&owlery, owner, shell_id); - let token = spt_daemon::shellhost::read_link_token(&shell_perch).expect("a link token is parked"); + let token = + spt_daemon::shellhost::read_link_token(&shell_perch).expect("a link token is parked"); let key = spt_daemon::shellhost::link_key(&token); assert_ne!( spt_store::shellinfo::read_shell_info(&shell_perch) @@ -164,9 +171,10 @@ fn a_payload_carrying_state_call_spools_a_durable_io_frame() { .map(|l| l.trim()) .filter(|l| !l.is_empty()) .map(|line| { - let frame = spt_daemon::shellchan::verify_stamped_frame(&key, line).unwrap_or_else( - || panic!("every spooled IO frame is MAC-stamped under the link: {line:?}"), - ); + let frame = + spt_daemon::shellchan::verify_stamped_frame(&key, line).unwrap_or_else(|| { + panic!("every spooled IO frame is MAC-stamped under the link: {line:?}") + }); spt_proto::event::parse_event(frame) .unwrap_or_else(|| panic!("a drained frame must parse: {frame:?}")) }) diff --git a/crates/spt/tests/job_escape_e2e.rs b/crates/spt/tests/job_escape_e2e.rs index f83829cf..3f5cbafe 100644 --- a/crates/spt/tests/job_escape_e2e.rs +++ b/crates/spt/tests/job_escape_e2e.rs @@ -150,8 +150,7 @@ mod win { /// ABSOLUTE powershell path (KH 5.12 no-bare-powershell) + `.no_window()`. /// Returns 0 if the query yields nothing (no child / dead parent). fn conhost_children_of(parent_pid: u32) -> usize { - const POWERSHELL_ABS: &str = - r"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"; + const POWERSHELL_ABS: &str = r"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"; let filter = format!("ParentProcessId={parent_pid}"); let script = format!( "@(Get-CimInstance Win32_Process -Filter '{filter}' | \ @@ -309,7 +308,9 @@ mod win { std::thread::spawn(move || { let _ = tx.send(cmd.output()); }); - rx.recv_timeout(Duration::from_secs(20)).ok().and_then(|r| r.ok()) + rx.recv_timeout(Duration::from_secs(20)) + .ok() + .and_then(|r| r.ok()) }; // taskkill /F /T — broker + brain + conhost subtree, but ONLY while the pid // still is the process pinned above (a `daemon stop` that already worked @@ -584,7 +585,10 @@ mod win { ); // ── Assertions. ── - assert!(daemon_alive_before, "PRECONDITION: daemon must be alive before the job terminate"); + assert!( + daemon_alive_before, + "PRECONDITION: daemon must be alive before the job terminate" + ); // Non-vacuity: the job really does kill its members. assert!( control_died, diff --git a/crates/spt/tests/json_emit.rs b/crates/spt/tests/json_emit.rs index a1fb2dcd..57385dc3 100644 --- a/crates/spt/tests/json_emit.rs +++ b/crates/spt/tests/json_emit.rs @@ -24,7 +24,11 @@ use spt_store::perch; /// Run `spt --json` under the isolated home, bounded so a wedged /// subprocess fails loud instead of hanging the suite. -fn run_json(spt_bin: &std::path::Path, home: &std::path::Path, args: &[&str]) -> std::process::Output { +fn run_json( + spt_bin: &std::path::Path, + home: &std::path::Path, + args: &[&str], +) -> std::process::Output { let mut cmd = Command::new(spt_bin); cmd.no_window() .args(args) @@ -45,7 +49,10 @@ fn run_json(spt_bin: &std::path::Path, home: &std::path::Path, args: &[&str]) -> fn parse_json(label: &str, out: &std::process::Output) -> serde_json::Value { let stdout = String::from_utf8_lossy(&out.stdout); let stderr = String::from_utf8_lossy(&out.stderr); - eprintln!("=== {label} --json ===\nstatus={}\nstdout=\n{stdout}\nstderr=\n{stderr}", out.status); + eprintln!( + "=== {label} --json ===\nstatus={}\nstdout=\n{stdout}\nstderr=\n{stderr}", + out.status + ); serde_json::from_str::(stdout.trim()).unwrap_or_else(|e| { panic!("{label} --json must emit parseable JSON, got non-JSON ({e}): stdout=\n{stdout}") }) @@ -90,7 +97,11 @@ fn json_flag_emits_parseable_json_for_read_status_subset() { // ── how-to (bare) → the topic list DTO ── let out = run_json(&spt_bin, home.path(), &["how-to"]); - assert!(out.status.success(), "how-to --json should exit 0: {:?}", out); + assert!( + out.status.success(), + "how-to --json should exit 0: {:?}", + out + ); let v = parse_json("how-to", &out); assert!( v.get("topics").map(|t| t.is_array()).unwrap_or(false), @@ -99,7 +110,11 @@ fn json_flag_emits_parseable_json_for_read_status_subset() { // ── adapter version → {adapter, version} DTO ── let out = run_json(&spt_bin, home.path(), &["adapter", "version", "cc"]); - assert!(out.status.success(), "adapter version --json should exit 0: {:?}", out); + assert!( + out.status.success(), + "adapter version --json should exit 0: {:?}", + out + ); let v = parse_json("adapter version", &out); assert_eq!( v.get("version").and_then(|s| s.as_str()), @@ -109,7 +124,11 @@ fn json_flag_emits_parseable_json_for_read_status_subset() { // ── daemon status → the status DTO (running=false here; still valid JSON) ── let out = run_json(&spt_bin, home.path(), &["daemon", "status"]); - assert!(out.status.success(), "daemon status --json should exit 0: {:?}", out); + assert!( + out.status.success(), + "daemon status --json should exit 0: {:?}", + out + ); let v = parse_json("daemon status", &out); assert!( v.get("running").map(|r| r.is_boolean()).unwrap_or(false), @@ -127,7 +146,10 @@ fn json_flag_emits_parseable_json_for_read_status_subset() { ("adapter list", ["adapter", "list"], "adapters"), ] { let out = run_json(&spt_bin, home.path(), &argv); - assert!(out.status.success(), "{label} --json should exit 0: {out:?}"); + assert!( + out.status.success(), + "{label} --json should exit 0: {out:?}" + ); let v = parse_json(label, &out); assert!( v.get(key).map(|a| a.is_array()).unwrap_or(false), diff --git a/crates/spt/tests/knock_approve_not_hostage_e2e.rs b/crates/spt/tests/knock_approve_not_hostage_e2e.rs index e4b1a849..9e9a6d0f 100644 --- a/crates/spt/tests/knock_approve_not_hostage_e2e.rs +++ b/crates/spt/tests/knock_approve_not_hostage_e2e.rs @@ -52,8 +52,6 @@ use spt_store::info::{self, InfoJson}; use spt_store::knock::{Knock, KnockState, KnockStore, TargetTier}; use spt_store::perch::{self, ParentHint}; - - fn now_ms() -> u64 { std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) @@ -242,8 +240,7 @@ fn an_approval_stands_and_exits_the_same_whether_or_not_its_wire_legs_arrive() { // the sentence REQ-KNOCK-MONIC-IMPART's own gate names, read off a process // that actually ran rather than off the composer. assert!( - r_err.contains("MONIC_IMPART_FAIL:") - && r_err.contains("the grant stands"), + r_err.contains("MONIC_IMPART_FAIL:") && r_err.contains("the grant stands"), "the impart reports its OWN failure and says what survives it:\n{r_err}" ); // And the failure it reports is still REACHABLE: a run that had quietly diff --git a/crates/spt/tests/knock_mutual_cross_node_e2e.rs b/crates/spt/tests/knock_mutual_cross_node_e2e.rs index 629504e7..242682ec 100644 --- a/crates/spt/tests/knock_mutual_cross_node_e2e.rs +++ b/crates/spt/tests/knock_mutual_cross_node_e2e.rs @@ -88,8 +88,6 @@ fn now_ms() -> u64 { .as_millis() as u64 } - - /// Run `f` with the process-global `SPT_HOME` pointed at `home`. /// /// The canonical store helpers are all ``-derived, so this is how the @@ -247,7 +245,10 @@ fn own_addr(home: &Path) -> (String, serde_json::Value) { if let Ok(mut b) = Brain::cold_start(&spt_daemon::broker_socket_name(), now_ms()) { if let Ok(s) = b.net_status() { if s.enabled && !s.addr.is_null() { - return (s.node_id_hex.expect("a net-up daemon names its node"), s.addr); + return ( + s.node_id_hex.expect("a net-up daemon names its node"), + s.addr, + ); } } } @@ -280,9 +281,7 @@ fn handed_code(stdout: &str) -> String { fn mint_on_b(spt: &Path, home_b: &Path) -> String { let mut cmd = Command::new(spt); cmd.no_window() - .args([ - "knock", "new-code", "--surfaces", "msg", "--subnet", SUBNET, - ]) + .args(["knock", "new-code", "--surfaces", "msg", "--subnet", SUBNET]) .env("SPT_HOME", home_b) .env("SPT_AGENT_ID", MINTER); let minted = common::output_bounded(cmd, Duration::from_secs(60)); @@ -478,7 +477,6 @@ fn a_cross_node_redemption_opens_the_presenters_own_side_and_only_asks_for_the_m "the reverse is the REDEEMER's own rule on the REDEEMER's node — the \ minting node holds no scope for them" ); - } /// Every file under `dir`, concatenated — the crude but honest way to assert a diff --git a/crates/spt/tests/knock_notfound_refuses_e2e.rs b/crates/spt/tests/knock_notfound_refuses_e2e.rs index 7bb9ee8c..b0bfc881 100644 --- a/crates/spt/tests/knock_notfound_refuses_e2e.rs +++ b/crates/spt/tests/knock_notfound_refuses_e2e.rs @@ -43,8 +43,6 @@ use common::CommandNoWindowExt; use spt_store::info::{self, InfoJson}; use spt_store::perch::{self, ParentHint}; - - /// A perch for `id`, with a pid no live process holds. This is an endpoint that /// EXISTS on this machine and has no registry row — precisely the target the /// local landing was built for. diff --git a/crates/spt/tests/list_json_liveness_parity_e2e.rs b/crates/spt/tests/list_json_liveness_parity_e2e.rs index 82012d3b..db883110 100644 --- a/crates/spt/tests/list_json_liveness_parity_e2e.rs +++ b/crates/spt/tests/list_json_liveness_parity_e2e.rs @@ -34,13 +34,13 @@ use spt_store::perch; // serialize anyway so a future sibling can't race the shared env (the e2e pattern). static E2E_LOCK: Mutex<()> = Mutex::new(()); - - /// Seed `name` as a member subnet (so `endpoint list` iterates it) via the real /// `SubnetStore` under the already-set `$SPT_HOME`. fn seed_subnet(name: &str) { let mut store = spt_store::subnet::SubnetStore::load(); - store.create_subnet(name, spt_store::access::Mode::Open).expect("seed subnet"); + store + .create_subnet(name, spt_store::access::Mode::Open) + .expect("seed subnet"); store.save().expect("save subnets"); } @@ -90,7 +90,13 @@ fn write_own_node_snapshot(subnet: &str, id: &str, status: Status) { fn write_pid_alive_gateway(id: &str) { let perch_path = perch::owlery_dir().join(id); std::fs::create_dir_all(&perch_path).unwrap(); - let rec = spt_store::info::InfoJson::new(id, "t", std::process::id(), &format!("sid-{id}"), "gateway"); + let rec = spt_store::info::InfoJson::new( + id, + "t", + std::process::id(), + &format!("sid-{id}"), + "gateway", + ); spt_store::info::write_info(&perch_path, &rec).unwrap(); } @@ -157,7 +163,10 @@ fn json_reconciles_self_owned_gateway_to_local_liveness() { common::output_bounded(cmd, Duration::from_secs(30)) }; let human_stdout = String::from_utf8_lossy(&human_out.stdout); - assert!(human_out.status.success(), "endpoint list (human) must succeed"); + assert!( + human_out.status.success(), + "endpoint list (human) must succeed" + ); // Restrict to the lines that mention the gateway — the human surface must not // read it Suspended/Offline (it discards the own-node gossip, shows roster truth). let gw_lines: String = human_stdout @@ -183,7 +192,8 @@ fn json_reconciles_self_owned_gateway_to_local_liveness() { --json, identical to the human/picker surface (REQ-LIST-JSON-LIVENESS-PARITY)" ); assert!( - !gw_lines.to_lowercase().contains("suspend") && !gw_lines.to_lowercase().contains("offline"), + !gw_lines.to_lowercase().contains("suspend") + && !gw_lines.to_lowercase().contains("offline"), "human and --json must AGREE the gateway is live — human read it non-Suspended.\n\ === gateway lines ===\n{gw_lines}" ); diff --git a/crates/spt/tests/listen_seed_retry_e2e.rs b/crates/spt/tests/listen_seed_retry_e2e.rs index 745abb72..910019ac 100644 --- a/crates/spt/tests/listen_seed_retry_e2e.rs +++ b/crates/spt/tests/listen_seed_retry_e2e.rs @@ -53,7 +53,9 @@ fn start_inproc_daemon() { fn seed_subnets(names: &[&str]) { let mut store = spt_store::subnet::SubnetStore::load(); for n in names { - store.create_subnet(n, spt_store::access::Mode::Open).expect("seed subnet"); + store + .create_subnet(n, spt_store::access::Mode::Open) + .expect("seed subnet"); } store.save().expect("save subnets"); } @@ -92,7 +94,14 @@ fn seed_survives_prebind_refusal_and_retry_binds() { let seed = Command::new(&spt) .no_window() .args([ - "api", "--adapter", "mock", "seed", "--pid", &anchor, "--session-id", session_id, + "api", + "--adapter", + "mock", + "seed", + "--pid", + &anchor, + "--session-id", + session_id, ]) .env("SPT_HOME", home.path()) .status() @@ -102,7 +111,16 @@ fn seed_survives_prebind_refusal_and_retry_binds() { // First listen: NO --subnet → HOME refusal AFTER the seed was taken. let refused = Command::new(&spt) .no_window() - .args(["api", "--adapter", "mock", "listen", id, "--parent-pid", &anchor, "--once"]) + .args([ + "api", + "--adapter", + "mock", + "listen", + id, + "--parent-pid", + &anchor, + "--once", + ]) .env("SPT_HOME", home.path()) .output() .expect("run first api listen"); @@ -129,8 +147,16 @@ fn seed_survives_prebind_refusal_and_retry_binds() { let retry = Command::new(&spt) .no_window() .args([ - "api", "--adapter", "mock", "listen", id, "--parent-pid", &anchor, "--subnet", - "work", "--once", + "api", + "--adapter", + "mock", + "listen", + id, + "--parent-pid", + &anchor, + "--subnet", + "work", + "--once", ]) .env("SPT_HOME", home.path()) .output() @@ -158,9 +184,16 @@ fn seed_survives_prebind_refusal_and_retry_binds() { // The perch bound live with the seed's session id, homed to the retry's subnet. let rec = spt_store::info::read_info(&perch_path).expect("perch info.json after retry"); - assert_eq!(rec.session_id, session_id, "the perch carries the seed's sid"); + assert_eq!( + rec.session_id, session_id, + "the perch carries the seed's sid" + ); assert_eq!(rec.state, "live_agent"); - assert_eq!(rec.home_subnet.as_deref(), Some("work"), "homed to the retry's --subnet"); + assert_eq!( + rec.home_subnet.as_deref(), + Some("work"), + "homed to the retry's --subnet" + ); } // [int->REQ-LISTEN-SESSION-ID-FALLBACK] F-034 leg c: a session with NO live seed @@ -189,8 +222,16 @@ fn no_seed_session_binds_via_session_id_fallback() { let listen = Command::new(&spt) .no_window() .args([ - "api", "--adapter", "mock", "listen", id, "--parent-pid", &anchor, "--session-id", - sid, "--once", + "api", + "--adapter", + "mock", + "listen", + id, + "--parent-pid", + &anchor, + "--session-id", + sid, + "--once", ]) .env("SPT_HOME", home.path()) .output() diff --git a/crates/spt/tests/live_adapt_translation_swap_e2e.rs b/crates/spt/tests/live_adapt_translation_swap_e2e.rs index ddb5f1eb..dc451a4e 100644 --- a/crates/spt/tests/live_adapt_translation_swap_e2e.rs +++ b/crates/spt/tests/live_adapt_translation_swap_e2e.rs @@ -74,8 +74,6 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - /// Lowercase-hex SHA-256 of a file (so we can assert the swap landed NEW bytes). fn file_hash(path: &Path) -> Option { use sha2::{Digest, Sha256}; @@ -256,7 +254,8 @@ fn adapter_apply_swaps_locked_translation_binary_without_restarting_endpoint() { .append(true) .open(&xlate_staged) .expect("open staged xlate to append padding"); - f.write_all(&[0u8; 4096]).expect("append padding to staged xlate"); + f.write_all(&[0u8; 4096]) + .expect("append padding to staged xlate"); } // The staging manifest declares the SAME absolute translation path (so the // post-swap install-dir manifest still points the broker at `/xlate`). @@ -288,9 +287,8 @@ fn adapter_apply_swaps_locked_translation_binary_without_restarting_endpoint() { // (b) the session/endpoint is STILL alive (no restart — brain-parity): the // harness pid is alive AND the perch is still ONLINE. ── let hash_after = file_hash(&xlate_install); - let swap_landed = hash_after.is_some() - && hash_after == hash_staged - && hash_after != hash_before; + let swap_landed = + hash_after.is_some() && hash_after == hash_staged && hash_after != hash_before; let harness_alive_after = harness_pid .map(spt_store::proc::is_process_alive) @@ -322,14 +320,15 @@ fn adapter_apply_swaps_locked_translation_binary_without_restarting_endpoint() { if let Some(p) = harness_pid { kill_pid(p); } - let psyche_perch = - perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); + let psyche_perch = perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); if let Some(p) = spt_store::info::read_pid(&psyche_perch) { kill_pid(p); } let _ = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -426,7 +425,11 @@ fn adapter_apply_with_no_matching_session_still_swaps() { .map(|e| format!(".{}", e.to_string_lossy())) .unwrap_or_default(); let xlate_fixture = common::sibling_bin("translate_proof_fixture"); - assert!(xlate_fixture.exists(), "fixture must be built: {}", xlate_fixture.display()); + assert!( + xlate_fixture.exists(), + "fixture must be built: {}", + xlate_fixture.display() + ); // The install dir holds the OLD xlate; a minimal manifest so read_translation_path // resolves (the apply reads it around the swap). NO adapter registration, NO @@ -473,14 +476,20 @@ fn adapter_apply_with_no_matching_session_still_swaps() { std::fs::copy(&xlate_fixture, &xlate_staged).unwrap(); { use std::io::Write; - let mut f = std::fs::OpenOptions::new().append(true).open(&xlate_staged).unwrap(); + let mut f = std::fs::OpenOptions::new() + .append(true) + .open(&xlate_staged) + .unwrap(); f.write_all(&[0u8; 4096]).unwrap(); } std::fs::write(staging.join("manifest.toml"), &manifest_toml).unwrap(); let hash_before = file_hash(&xlate_install); let hash_staged = file_hash(&xlate_staged); - assert_ne!(hash_before, hash_staged, "PRECONDITION: staged xlate must differ"); + assert_ne!( + hash_before, hash_staged, + "PRECONDITION: staged xlate must differ" + ); // ── The delegated apply with ZERO matching sessions. ── let mut brain = Brain::cold_start(&broker_socket_name(), now_ms()) @@ -507,7 +516,9 @@ fn adapter_apply_with_no_matching_session_still_swaps() { // ── Reap SCOPED before asserting. ── let _ = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -568,8 +579,16 @@ fn adapter_apply_swaps_composite_profile_endpoint_matched_on_parent() { .unwrap_or_default(); let mock_session = common::sibling_bin("mock-session"); let xlate_fixture = common::sibling_bin("translate_proof_fixture"); - assert!(mock_session.exists(), "dummy-harness must be built: {}", mock_session.display()); - assert!(xlate_fixture.exists(), "fixture must be built: {}", xlate_fixture.display()); + assert!( + mock_session.exists(), + "dummy-harness must be built: {}", + mock_session.display() + ); + assert!( + xlate_fixture.exists(), + "fixture must be built: {}", + xlate_fixture.display() + ); // Register adapter `cc` with a trivial (empty overlay) `[profiles.prof]` so // `--adapter cc:prof` resolves. The install dir + absolute translation path are @@ -687,13 +706,17 @@ fn adapter_apply_swaps_composite_profile_endpoint_matched_on_parent() { .append(true) .open(&xlate_staged) .expect("open staged xlate to append padding"); - f.write_all(&[0u8; 4096]).expect("append padding to staged xlate"); + f.write_all(&[0u8; 4096]) + .expect("append padding to staged xlate"); } std::fs::write(staging.join("manifest.toml"), &manifest_toml).unwrap(); let hash_before = file_hash(&xlate_install); let hash_staged = file_hash(&xlate_staged); - assert_ne!(hash_before, hash_staged, "PRECONDITION: staged xlate must differ"); + assert_ne!( + hash_before, hash_staged, + "PRECONDITION: staged xlate must differ" + ); // ── The apply carries the bare PARENT `cc` — the composite `cc:prof` session // must be selected by the parent-matcher. ── @@ -709,7 +732,9 @@ fn adapter_apply_swaps_composite_profile_endpoint_matched_on_parent() { let hash_after = file_hash(&xlate_install); let swap_landed = hash_after.is_some() && hash_after == hash_staged && hash_after != hash_before; - let harness_alive_after = harness_pid.map(spt_store::proc::is_process_alive).unwrap_or(false); + let harness_alive_after = harness_pid + .map(spt_store::proc::is_process_alive) + .unwrap_or(false); let mut still_online = false; let online_deadline = Instant::now() + Duration::from_secs(8); while Instant::now() < online_deadline { @@ -741,7 +766,9 @@ fn adapter_apply_swaps_composite_profile_endpoint_matched_on_parent() { } let _ = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -749,7 +776,10 @@ fn adapter_apply_swaps_composite_profile_endpoint_matched_on_parent() { let _ = broker.wait(); // ── ASSERTIONS ── - assert!(run.status.success(), "endpoint start must succeed: {run_stderr}"); + assert!( + run.status.success(), + "endpoint start must succeed: {run_stderr}" + ); assert!( online, "PRECONDITION: the cc:prof composite endpoint must bind ONLINE before the apply.\n\ @@ -829,8 +859,16 @@ fn adapter_apply_for_foreign_adapter_leaves_live_endpoint_untouched() { .unwrap_or_default(); let mock_session = common::sibling_bin("mock-session"); let xlate_fixture = common::sibling_bin("translate_proof_fixture"); - assert!(mock_session.exists(), "dummy-harness must be built: {}", mock_session.display()); - assert!(xlate_fixture.exists(), "fixture must be built: {}", xlate_fixture.display()); + assert!( + mock_session.exists(), + "dummy-harness must be built: {}", + mock_session.display() + ); + assert!( + xlate_fixture.exists(), + "fixture must be built: {}", + xlate_fixture.display() + ); // Register the LIVE adapter `cc` (the endpoint we run). let install_dir = perch::spt_home().join("srcs").join("cc"); @@ -950,7 +988,10 @@ fn adapter_apply_for_foreign_adapter_leaves_live_endpoint_untouched() { let cc_hash_before = file_hash(&xlate_install); let other_before = file_hash(&other_xlate); let other_staged_hash = file_hash(&other_staged); - assert_ne!(other_before, other_staged_hash, "PRECONDITION: staged other xlate must differ"); + assert_ne!( + other_before, other_staged_hash, + "PRECONDITION: staged other xlate must differ" + ); // ── The FOREIGN apply: adapter `other`, its own install/staging dirs. The `cc` // session must NOT be selected (parent-matcher: `cc` != `other`). ── @@ -968,7 +1009,9 @@ fn adapter_apply_for_foreign_adapter_leaves_live_endpoint_untouched() { let cc_untouched = cc_hash_after.is_some() && cc_hash_after == cc_hash_before; let other_swapped = other_after.is_some() && other_after == other_staged_hash && other_after != other_before; - let harness_alive_after = harness_pid.map(spt_store::proc::is_process_alive).unwrap_or(false); + let harness_alive_after = harness_pid + .map(spt_store::proc::is_process_alive) + .unwrap_or(false); let mut still_online = false; let online_deadline = Instant::now() + Duration::from_secs(8); while Instant::now() < online_deadline { @@ -1001,7 +1044,9 @@ fn adapter_apply_for_foreign_adapter_leaves_live_endpoint_untouched() { } let _ = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -1009,7 +1054,10 @@ fn adapter_apply_for_foreign_adapter_leaves_live_endpoint_untouched() { let _ = broker.wait(); // ── ASSERTIONS ── - assert!(run.status.success(), "endpoint start must succeed: {run_stderr}"); + assert!( + run.status.success(), + "endpoint start must succeed: {run_stderr}" + ); assert!( online, "PRECONDITION: the cc endpoint must bind ONLINE before the foreign apply.\n\ diff --git a/crates/spt/tests/live_bind_firsthost_e2e.rs b/crates/spt/tests/live_bind_firsthost_e2e.rs index b5947af2..99869fe5 100644 --- a/crates/spt/tests/live_bind_firsthost_e2e.rs +++ b/crates/spt/tests/live_bind_firsthost_e2e.rs @@ -46,8 +46,6 @@ fn start_inproc_daemon() { panic!("in-process seed daemon did not come up"); } - - #[test] fn live_bind_marks_online_and_brain_reconcile_hosts() { let home = tempfile::tempdir().unwrap(); @@ -85,10 +83,23 @@ fn live_bind_marks_online_and_brain_reconcile_hosts() { // and marks it online (the W0.3 first-host handoff). The Psyche does NOT spawn // in this process — bind only writes the online signal. let out = spt(&[ - "api", "--adapter", "mocklive", "--manifest", &mp, "bind", "agent8", - "--type", "live_agent", "--set-session-id", "sid-1", + "api", + "--adapter", + "mocklive", + "--manifest", + &mp, + "bind", + "agent8", + "--type", + "live_agent", + "--set-session-id", + "sid-1", ]); - assert!(out.status.success(), "bind: {}", String::from_utf8_lossy(&out.stderr)); + assert!( + out.status.success(), + "bind: {}", + String::from_utf8_lossy(&out.stderr) + ); // The real establish-marks-online: written by cmd_bind, NOT hand-seeded. let self_perch = perch::resolve_perch_path("agent8", ParentHint::Infer); @@ -141,7 +152,10 @@ fn live_bind_marks_online_and_brain_reconcile_hosts() { &cfg, StartReason::Cold, ); - assert!(set.is_empty(), "an offline transition un-hosts the lifecycle"); + assert!( + set.is_empty(), + "an offline transition un-hosts the lifecycle" + ); // Reap any REAL daemon that auto-started against this throwaway home (hygiene). // AUTHENTICATED: `daemon.pid` is a number, not an identity — a breadcrumb whose diff --git a/crates/spt/tests/live_firsthost_e2e.rs b/crates/spt/tests/live_firsthost_e2e.rs index 9775bb45..8bf85731 100644 --- a/crates/spt/tests/live_firsthost_e2e.rs +++ b/crates/spt/tests/live_firsthost_e2e.rs @@ -87,18 +87,41 @@ fn live_listen_marks_online_and_brain_reconcile_hosts() { // ── seed (keyed by THIS process's pid — alive, passes the recycle guard) ── let out = spt(&[ - "api", "--adapter", "mocklive", "seed", "--pid", &pid, "--session-id", "sid-1", + "api", + "--adapter", + "mocklive", + "seed", + "--pid", + &pid, + "--session-id", + "sid-1", ]); - assert!(out.status.success(), "seed: {}", String::from_utf8_lossy(&out.stderr)); + assert!( + out.status.success(), + "seed: {}", + String::from_utf8_lossy(&out.stderr) + ); // ── the REAL live listen --once: binds the Self perch + marks it online // (the W0.2 establish-marks-online), drains, exits. The Psyche does NOT spawn // in this process anymore. let out = spt(&[ - "api", "--adapter", "mocklive", "--manifest", &mp, "listen", "agent7", - "--parent-pid", &pid, "--once", + "api", + "--adapter", + "mocklive", + "--manifest", + &mp, + "listen", + "agent7", + "--parent-pid", + &pid, + "--once", ]); - assert!(out.status.success(), "listen: {}", String::from_utf8_lossy(&out.stderr)); + assert!( + out.status.success(), + "listen: {}", + String::from_utf8_lossy(&out.stderr) + ); // The real establish-marks-online: the perch carries status=online, written by // cmd_listen (NOT hand-seeded). @@ -147,7 +170,10 @@ fn live_listen_marks_online_and_brain_reconcile_hosts() { &cfg, StartReason::Cold, ); - assert!(set.is_empty(), "an offline transition un-hosts the lifecycle"); + assert!( + set.is_empty(), + "an offline transition un-hosts the lifecycle" + ); // Reap any REAL daemon that auto-started against this throwaway home (hygiene). // AUTHENTICATED: `daemon.pid` is a number, not an identity — a breadcrumb whose diff --git a/crates/spt/tests/live_resolve_e2e.rs b/crates/spt/tests/live_resolve_e2e.rs index 0715fd64..103335eb 100644 --- a/crates/spt/tests/live_resolve_e2e.rs +++ b/crates/spt/tests/live_resolve_e2e.rs @@ -136,7 +136,10 @@ fn listen_without_adapter_resolves_from_host_binaries() { assert!(out.status.success(), "{}", diag("pointer listen", &out)); let perch_b = perch::resolve_perch_path("agent-b", ParentHint::Infer); assert_eq!( - spt_store::info::read_info(&perch_b).unwrap().adapter.as_deref(), + spt_store::info::read_info(&perch_b) + .unwrap() + .adapter + .as_deref(), Some("older-spt"), "the active-profile pointer wins over the freshest-registered fallback" ); diff --git a/crates/spt/tests/livehost_bootgate_e2e.rs b/crates/spt/tests/livehost_bootgate_e2e.rs index 92f39283..7d299ad5 100644 --- a/crates/spt/tests/livehost_bootgate_e2e.rs +++ b/crates/spt/tests/livehost_bootgate_e2e.rs @@ -154,8 +154,7 @@ fn cold_start_does_not_revive_a_sessionless_online_latched_perch() { // ── (5b) NO PHANTOM: the nested `{id}-psyche` perch must NEVER appear (host_one // writes it only on a Psyche spawn). Give a host-attempt window past the offline // flip to be sure no late tick revived it. ── - let psyche_perch = - perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); + let psyche_perch = perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); let settle = Instant::now() + Duration::from_secs(8); while Instant::now() < settle { std::thread::sleep(Duration::from_millis(200)); diff --git a/crates/spt/tests/midturn_span_e2e.rs b/crates/spt/tests/midturn_span_e2e.rs index 4a937e86..afefb505 100644 --- a/crates/spt/tests/midturn_span_e2e.rs +++ b/crates/spt/tests/midturn_span_e2e.rs @@ -129,7 +129,8 @@ fn poll(spt_bin: &Path, home: &Path, id: &str, sid: &str) -> serde_json::Value { String::from_utf8_lossy(&out.stderr) ); let text = String::from_utf8_lossy(&out.stdout).to_string(); - serde_json::from_str(&text).unwrap_or_else(|e| panic!("poll output is not JSON ({e}): {text:?}")) + serde_json::from_str(&text) + .unwrap_or_else(|e| panic!("poll output is not JSON ({e}): {text:?}")) } /// `(kind, mid, payload)` per event, in log order — the whole shape this lane @@ -215,7 +216,10 @@ fn a_mid_span_rides_busy_as_agent_output_and_the_close_carries_no_marker() { assert!(err.contains("STATE_MID_ON_IDLE"), "named refusal: {err}"); let no_payload = rig.ingest("busy", None, &["--mid"]); - assert!(!no_payload.status.success(), "--mid with no payload refused"); + assert!( + !no_payload.status.success(), + "--mid with no payload refused" + ); let err = String::from_utf8_lossy(&no_payload.stderr).to_string(); assert!(err.contains("STATE_MID_NO_PAYLOAD"), "named refusal: {err}"); @@ -279,7 +283,11 @@ fn a_bare_seal_marker_is_refused_in_a_span_and_mints_at_the_close() { let body = std::panic::catch_unwind(|| { // A bare trailing marker inside a MID-TURN span: nothing is sealed, and // the refusal lands on the shipped confirmation surface by name. - let out = rig.ingest("busy", Some("working on it ;;seal everything after this"), &["--mid"]); + let out = rig.ingest( + "busy", + Some("working on it ;;seal everything after this"), + &["--mid"], + ); assert!( out.status.success(), "the ingest itself still succeeds: {}", diff --git a/crates/spt/tests/multi_subnet_bringup_e2e.rs b/crates/spt/tests/multi_subnet_bringup_e2e.rs index 2dfbbb0d..792f220c 100644 --- a/crates/spt/tests/multi_subnet_bringup_e2e.rs +++ b/crates/spt/tests/multi_subnet_bringup_e2e.rs @@ -57,8 +57,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - fn ready_pid(path: &Path) -> Option { let s = std::fs::read_to_string(path).ok()?; serde_json::from_str::(&s) @@ -79,8 +77,6 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - /// Seed `names` as subnets this node is a member of (the multi-subnet precondition /// `assign_home` keys on: 0→local-only, 1→auto, ≥2→ambiguous). The FIRST name is /// the intended control home. Writes through the real `SubnetStore` into the @@ -88,7 +84,9 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { fn seed_subnets(names: &[&str]) { let mut store = spt_store::subnet::SubnetStore::load(); for n in names { - store.create_subnet(n, spt_store::access::Mode::Open).expect("seed subnet"); + store + .create_subnet(n, spt_store::access::Mode::Open) + .expect("seed subnet"); } store.save().expect("save subnets"); } @@ -163,7 +161,9 @@ fn reap(home: &Path, spt_bin: &Path, broker: &mut Child, brain_pid: u32, extra: } let _ = { let mut cmd = Command::new(spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -175,7 +175,11 @@ fn reap(home: &Path, spt_bin: &Path, broker: &mut Child, brain_pid: u32, extra: fn wait_status(perch_path: &Path, want: &str, budget: Duration) -> bool { let deadline = Instant::now() + budget; while Instant::now() < deadline { - if spt_store::info::read_info(perch_path).and_then(|i| i.status).as_deref() == Some(want) { + if spt_store::info::read_info(perch_path) + .and_then(|i| i.status) + .as_deref() + == Some(want) + { return true; } std::thread::sleep(Duration::from_millis(120)); @@ -206,7 +210,10 @@ fn multi_subnet_refuses_without_subnet_then_homes_and_binds() { std::env::set_var("SPT_HOME", home.path()); let spt_bin = PathBuf::from(env!("CARGO_BIN_EXE_spt")); let mock = common::sibling_bin("mock-session"); - assert!(mock.exists(), "build the dummy harness: cargo build -p mock-adapter --bin mock-session"); + assert!( + mock.exists(), + "build the dummy harness: cargo build -p mock-adapter --bin mock-session" + ); // ≥2 subnets — the gap only exists here (a single-subnet node auto-homes). // FIRST = the control home we will pin with --subnet. @@ -239,7 +246,13 @@ fn multi_subnet_refuses_without_subnet_then_homes_and_binds() { let mut cmd = Command::new(&spt_bin); cmd.no_window() .args([ - "endpoint", "create", home_id, "--adapter", "dummyharness", "--subnet", control, + "endpoint", + "create", + home_id, + "--adapter", + "dummyharness", + "--subnet", + control, ]) .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) @@ -257,7 +270,11 @@ fn multi_subnet_refuses_without_subnet_then_homes_and_binds() { common::output_bounded(cmd, Duration::from_secs(45)) }; let home_perch = perch::resolve_perch_path(home_id, ParentHint::Infer); - let online = wait_status(&home_perch, spt_store::liveness::STATUS_ONLINE, Duration::from_secs(20)); + let online = wait_status( + &home_perch, + spt_store::liveness::STATUS_ONLINE, + Duration::from_secs(20), + ); // Read the inherited home + sync scope (compute pre-reap). let bound_home = spt_store::info::read_info(&home_perch).and_then(|i| i.home_subnet); @@ -267,16 +284,30 @@ fn multi_subnet_refuses_without_subnet_then_homes_and_binds() { let brain_stderr = common::daemon_stderr_panel(&brain_log); let harness_pid = harness_pid_of(&String::from_utf8_lossy(&run.stderr)); - reap(home.path(), &spt_bin, &mut broker, brain_pid, harness_pid.as_slice(), home_id); + reap( + home.path(), + &spt_bin, + &mut broker, + brain_pid, + harness_pid.as_slice(), + home_id, + ); // ── Assertions. ── - assert_ne!(refuse.status.code(), Some(0), "no-subnet multi-home mint must NOT succeed"); + assert_ne!( + refuse.status.code(), + Some(0), + "no-subnet multi-home mint must NOT succeed" + ); assert!( refuse_err.contains("MULTI_SUBNET_HOME"), "must refuse with the MULTI_SUBNET_HOME --subnet guidance (not a silent 25s timeout).\n\ === run stderr ===\n{refuse_err}" ); - assert!(!refuse_skeleton, "a refused mint must write NO skeleton perch"); + assert!( + !refuse_skeleton, + "a refused mint must write NO skeleton perch" + ); assert!( run.status.success(), @@ -336,16 +367,38 @@ fn single_subnet_control_auto_homes() { common::output_bounded(cmd, Duration::from_secs(45)) }; let perch_path = perch::resolve_perch_path(id, ParentHint::Infer); - let online = wait_status(&perch_path, spt_store::liveness::STATUS_ONLINE, Duration::from_secs(20)); + let online = wait_status( + &perch_path, + spt_store::liveness::STATUS_ONLINE, + Duration::from_secs(20), + ); let bound_home = spt_store::info::read_info(&perch_path).and_then(|i| i.home_subnet); let brain_stderr = common::daemon_stderr_panel(&brain_log); let harness_pid = harness_pid_of(&String::from_utf8_lossy(&run.stderr)); - reap(home.path(), &spt_bin, &mut broker, brain_pid, harness_pid.as_slice(), id); + reap( + home.path(), + &spt_bin, + &mut broker, + brain_pid, + harness_pid.as_slice(), + id, + ); - assert!(run.status.success(), "single-subnet run: {}", String::from_utf8_lossy(&run.stderr)); - assert!(online, "single-subnet auto-home must bind ONLINE.\n{brain_stderr}"); - assert_eq!(bound_home.as_deref(), Some("solo"), "auto-homed to the sole subnet"); + assert!( + run.status.success(), + "single-subnet run: {}", + String::from_utf8_lossy(&run.stderr) + ); + assert!( + online, + "single-subnet auto-home must bind ONLINE.\n{brain_stderr}" + ); + assert_eq!( + bound_home.as_deref(), + Some("solo"), + "auto-homed to the sole subnet" + ); } // ── (3) Fresh-UNBOUND attach-before-bind ─────────────────────────────────────── @@ -386,7 +439,11 @@ fn fresh_unbound_is_attachable_before_bind() { let harness_pid = harness_pid_of(&String::from_utf8_lossy(&run.stderr)); // The perch is UNBOUND (skeleton written UNBOUND, never bound) — and STAYS so. - let is_unbound = wait_status(&perch_path, spt_store::liveness::STATUS_UNBOUND, Duration::from_secs(15)); + let is_unbound = wait_status( + &perch_path, + spt_store::liveness::STATUS_UNBOUND, + Duration::from_secs(15), + ); // rc ATTACH the live pre-bind session → the heartbeat must flow. let rc_err = home.path().join("rc.stderr.log"); @@ -430,7 +487,9 @@ fn fresh_unbound_is_attachable_before_bind() { // Re-read status AFTER the attach: it must STILL be UNBOUND — proving the attach // landed on a genuinely pre-bind session, never a bound one. - let still_unbound = spt_store::info::read_info(&perch_path).and_then(|i| i.status).as_deref() + let still_unbound = spt_store::info::read_info(&perch_path) + .and_then(|i| i.status) + .as_deref() == Some(spt_store::liveness::STATUS_UNBOUND); let rc_stderr = std::fs::read_to_string(&rc_err).unwrap_or_default(); let rc_connected = rc_stderr.contains("PUMP_IPC_READER") && !rc_stderr.contains("RC_FAIL"); @@ -439,9 +498,20 @@ fn fresh_unbound_is_attachable_before_bind() { kill_pid(rc.id()); let _ = rc.kill(); let _ = rc.wait(); - reap(home.path(), &spt_bin, &mut broker, brain_pid, harness_pid.as_slice(), id); + reap( + home.path(), + &spt_bin, + &mut broker, + brain_pid, + harness_pid.as_slice(), + id, + ); - assert!(run.status.success(), "hold-unbound run --start: {}", String::from_utf8_lossy(&run.stderr)); + assert!( + run.status.success(), + "hold-unbound run --start: {}", + String::from_utf8_lossy(&run.stderr) + ); assert!( is_unbound, "the skeleton must be STATUS_UNBOUND (hold-unbound never binds).\n{brain_stderr}" diff --git a/crates/spt/tests/nested_resolution_e2e.rs b/crates/spt/tests/nested_resolution_e2e.rs index e92a2065..e5b00638 100644 --- a/crates/spt/tests/nested_resolution_e2e.rs +++ b/crates/spt/tests/nested_resolution_e2e.rs @@ -41,14 +41,14 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - /// Seed `names` as subnets this node belongs to (the multi-subnet precondition /// `assign_home` keys on: ≥2 → Ambiguous without a pick). fn seed_subnets(names: &[&str]) { let mut store = spt_store::subnet::SubnetStore::load(); for n in names { - store.create_subnet(n, spt_store::access::Mode::Open).expect("seed subnet"); + store + .create_subnet(n, spt_store::access::Mode::Open) + .expect("seed subnet"); } store.save().expect("save subnets"); } @@ -57,7 +57,13 @@ fn seed_subnets(names: &[&str]) { fn seed_homed_parent(id: &str, home: &str) { let path = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&path).unwrap(); - let mut rec = InfoJson::new(id, "2026-06-01T00:00:00Z", std::process::id(), "sid", "live_agent"); + let mut rec = InfoJson::new( + id, + "2026-06-01T00:00:00Z", + std::process::id(), + "sid", + "live_agent", + ); rec.home_subnet = Some(home.to_string()); info::write_info(&path, &rec).unwrap(); } diff --git a/crates/spt/tests/oneliner_e2e.rs b/crates/spt/tests/oneliner_e2e.rs index d93f264a..8ce4696f 100644 --- a/crates/spt/tests/oneliner_e2e.rs +++ b/crates/spt/tests/oneliner_e2e.rs @@ -211,8 +211,8 @@ fn install_script_against_staged_release() { // [unit->REQ-INSTALL-10] #[test] fn at_logon_task_launches_daemon_in_background_not_foreground() { - let ps1 = std::fs::read_to_string(installer_dir().join("install.ps1")) - .expect("read install.ps1"); + let ps1 = + std::fs::read_to_string(installer_dir().join("install.ps1")).expect("read install.ps1"); // The line that registers the at-logon task action. let task_line = ps1 .lines() diff --git a/crates/spt/tests/poll_envelope_e2e.rs b/crates/spt/tests/poll_envelope_e2e.rs index 6f349ac4..1ee95621 100644 --- a/crates/spt/tests/poll_envelope_e2e.rs +++ b/crates/spt/tests/poll_envelope_e2e.rs @@ -55,7 +55,11 @@ fn api_poll_emits_whole_self_delimiting_events() { // Two offline sends spool (the perch exists but holds no live listener). // The first body is multi-LINE on purpose: it must arrive as ONE whole // envelope (newline escaped to
), proving self-delimiting framing. - let q1 = send(home, &["send", "doyle", "--from", "alice"], "line one\nline two"); + let q1 = send( + home, + &["send", "doyle", "--from", "alice"], + "line one\nline two", + ); assert!(q1.contains("QUEUED:doyle"), "first send spools: {q1:?}"); let q2 = send(home, &["send", "doyle", "--from", "bob"], "second message"); assert!(q2.contains("QUEUED:doyle"), "second send spools: {q2:?}"); @@ -83,8 +87,7 @@ fn api_poll_emits_whole_self_delimiting_events() { } // Oldest first; the multi-line body rides as ONE line, newline →
. assert_eq!( - lines[0], - r#"line one
line two
"#, + lines[0], r#"line one
line two
"#, "multi-line body is one whole self-delimiting envelope" ); assert_eq!( diff --git a/crates/spt/tests/projindex_reader_e2e.rs b/crates/spt/tests/projindex_reader_e2e.rs index f211ccce..b6a4d947 100644 --- a/crates/spt/tests/projindex_reader_e2e.rs +++ b/crates/spt/tests/projindex_reader_e2e.rs @@ -28,8 +28,6 @@ use common::CommandNoWindowExt; use spt_store::contextstore::ContextStore; use spt_store::projindex::{self, IndexRead}; - - fn kill_pid(pid: u32) { #[cfg(windows)] let _ = Command::new("taskkill") @@ -40,8 +38,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - fn read_ready(path: &Path) -> Option { let v: serde_json::Value = serde_json::from_str(&std::fs::read_to_string(path).ok()?).ok()?; Some(v.get("pid")?.as_u64()? as u32) @@ -177,8 +173,11 @@ fn readers_answer_from_daemon_maintained_index_with_zero_git() { // ── (4) The reader verbs, git-poisoned, against the daemon-built index. ── let list_json = run_poisoned(&["endpoint", "list", "--json"]); - assert!(list_json.status.success(), "list --json failed: {}", - String::from_utf8_lossy(&list_json.stderr)); + assert!( + list_json.status.success(), + "list --json failed: {}", + String::from_utf8_lossy(&list_json.stderr) + ); let v: serde_json::Value = serde_json::from_slice(&list_json.stdout).unwrap(); let local = v["local"].as_array().expect("local rows"); let project_of = |id: &str| -> Option { @@ -207,8 +206,11 @@ fn readers_answer_from_daemon_maintained_index_with_zero_git() { ); let info = run_poisoned(&["api", "endpoint-info", "ep1"]); - assert!(info.status.success(), "endpoint-info failed: {}", - String::from_utf8_lossy(&info.stderr)); + assert!( + info.status.success(), + "endpoint-info failed: {}", + String::from_utf8_lossy(&info.stderr) + ); let payload: serde_json::Value = serde_json::from_slice(&info.stdout).unwrap(); assert_eq!( payload["project"].as_str(), @@ -249,13 +251,20 @@ fn readers_answer_from_daemon_maintained_index_with_zero_git() { std::thread::sleep(Duration::from_millis(200)); } } - assert_eq!(shim_violations(), "", "maintenance polling spawned no reader git"); + assert_eq!( + shim_violations(), + "", + "maintenance polling spawned no reader git" + ); // ── (6) Degradation: the index deleted out from under the readers — // verbs stay fast, render no attribution, still ZERO git. ── std::fs::remove_file(&index_path).unwrap(); let degraded = run_poisoned(&["endpoint", "list", "--json"]); - assert!(degraded.status.success(), "a missing index must not fail the list"); + assert!( + degraded.status.success(), + "a missing index must not fail the list" + ); let v: serde_json::Value = serde_json::from_slice(°raded.stdout).unwrap(); assert!( v["local"] @@ -265,7 +274,11 @@ fn readers_answer_from_daemon_maintained_index_with_zero_git() { .all(|r| r["project"].is_null()), "absent index → every project column degrades to '-' (null)" ); - assert_eq!(shim_violations(), "", "the degraded read spawned no git either"); + assert_eq!( + shim_violations(), + "", + "the degraded read spawned no git either" + ); // ── (7) Reap SCOPED. ── let _ = { diff --git a/crates/spt/tests/projindex_writer_e2e.rs b/crates/spt/tests/projindex_writer_e2e.rs index 2fd4564a..08a64013 100644 --- a/crates/spt/tests/projindex_writer_e2e.rs +++ b/crates/spt/tests/projindex_writer_e2e.rs @@ -43,7 +43,10 @@ fn kill_pid(pid: u32) { /// `(pid, generation)` out of `brain.ready`; `None` until it parses. fn read_ready(path: &Path) -> Option<(u32, u64)> { let v: serde_json::Value = serde_json::from_str(&std::fs::read_to_string(path).ok()?).ok()?; - Some((v.get("pid")?.as_u64()? as u32, v.get("generation")?.as_u64()?)) + Some(( + v.get("pid")?.as_u64()? as u32, + v.get("generation")?.as_u64()?, + )) } /// Poll `brain.ready` until it holds a pid different from `was`, up to `budget`. @@ -165,9 +168,12 @@ fn writer_cold_warm_and_event_invalidation_against_live_daemon() { // Cold publish: rows for every perch, precedence via the shared kernel. // [int->REQ-PROJECT-INDEX-WRITER] - let cold = wait_index(&index_path, Duration::from_secs(20), "cold publish", |idx| { - idx.endpoints.len() == 3 - }); + let cold = wait_index( + &index_path, + Duration::from_secs(20), + "cold publish", + |idx| idx.endpoints.len() == 3, + ); assert_eq!(cold.endpoints["ep1"].source.as_deref(), Some("session-cwd")); assert_eq!(cold.endpoints["ep1"].display.as_deref(), Some("proj-a")); assert_eq!(cold.endpoints["ep2"].source.as_deref(), Some("origin-cwd")); @@ -212,12 +218,11 @@ fn writer_cold_warm_and_event_invalidation_against_live_daemon() { let _ = broker.wait(); let bytes_before = std::fs::read(&index_path).unwrap(); let stats_path = home.path().join("index").join("project-index-stats.json"); - let run_before: u64 = serde_json::from_str::( - &std::fs::read_to_string(&stats_path).unwrap(), - ) - .unwrap()["last_run_ms"] - .as_u64() - .unwrap(); + let run_before: u64 = + serde_json::from_str::(&std::fs::read_to_string(&stats_path).unwrap()) + .unwrap()["last_run_ms"] + .as_u64() + .unwrap(); let brain_log2 = home.path().join("brain2.stderr.log"); let mut broker2: Child = spawn_daemon(&brain_log2); @@ -287,9 +292,16 @@ fn writer_cold_warm_and_event_invalidation_against_live_daemon() { id: "ep3".to_string(), cwd: Some(dir_c.to_string_lossy().to_string()), }); - let idx = wait_index(&index_path, Duration::from_secs(15), "session event → ep3 row", |i| { - i.endpoints.get("ep3").is_some_and(|e| e.source.as_deref() == Some("session-cwd")) - }); + let idx = wait_index( + &index_path, + Duration::from_secs(15), + "session event → ep3 row", + |i| { + i.endpoints + .get("ep3") + .is_some_and(|e| e.source.as_deref() == Some("session-cwd")) + }, + ); assert_eq!(idx.endpoints["ep3"].display.as_deref(), Some("proj-c")); // (4b) CONTEXT: a committed slice gives ep2 membership in `beta` — the @@ -297,12 +309,17 @@ fn writer_cold_warm_and_event_invalidation_against_live_daemon() { let slice = cs.project_context_path("beta", "ep2").unwrap(); std::fs::write(&slice, "ep2 in beta").unwrap(); cs.commit_project("beta", "ep2 slice").unwrap().unwrap(); - wait_index(&index_path, Duration::from_secs(15), "context commit → new generation", |i| { - i.source_generation != cold.source_generation + wait_index( + &index_path, + Duration::from_secs(15), + "context commit → new generation", + |i| { + i.source_generation != cold.source_generation // ep2's RENDERED attribution stays origin-cwd (higher precedence); // the membership refresh is visible through the generation move. && i.endpoints.get("ep2").is_some_and(|e| e.source.as_deref() == Some("origin-cwd")) - }); + }, + ); // (4c) RENAME through the real CLI verb (offline perch): row follows the id. let rename = { @@ -317,9 +334,12 @@ fn writer_cold_warm_and_event_invalidation_against_live_daemon() { "rename failed: {}", String::from_utf8_lossy(&rename.stderr) ); - let idx = wait_index(&index_path, Duration::from_secs(15), "rename → row moves", |i| { - i.endpoints.contains_key("ep1r") && !i.endpoints.contains_key("ep1") - }); + let idx = wait_index( + &index_path, + Duration::from_secs(15), + "rename → row moves", + |i| i.endpoints.contains_key("ep1r") && !i.endpoints.contains_key("ep1"), + ); assert_eq!( idx.endpoints["ep1r"].display.as_deref(), Some("proj-a"), @@ -331,9 +351,16 @@ fn writer_cold_warm_and_event_invalidation_against_live_daemon() { // fork nudge composes the new row from its copied membership. write_perch(&owlery, "forked", None, None); cs.fork_endpoint("ep1r", "forked").unwrap(); - let idx = wait_index(&index_path, Duration::from_secs(15), "fork → new row", |i| { - i.endpoints.get("forked").is_some_and(|e| e.project_id.is_some()) - }); + let idx = wait_index( + &index_path, + Duration::from_secs(15), + "fork → new row", + |i| { + i.endpoints + .get("forked") + .is_some_and(|e| e.project_id.is_some()) + }, + ); assert_eq!( idx.endpoints["forked"].source.as_deref(), Some("context-recency"), @@ -353,9 +380,12 @@ fn writer_cold_warm_and_event_invalidation_against_live_daemon() { "purge failed: {}", String::from_utf8_lossy(&purge.stderr) ); - wait_index(&index_path, Duration::from_secs(15), "purge → row dropped", |i| { - !i.endpoints.contains_key("ep2") - }); + wait_index( + &index_path, + Duration::from_secs(15), + "purge → row dropped", + |i| !i.endpoints.contains_key("ep2"), + ); // ── (5) Reap SCOPED. ── let _ = { diff --git a/crates/spt/tests/psyche_download_e2e.rs b/crates/spt/tests/psyche_download_e2e.rs index b90fae26..f6578089 100644 --- a/crates/spt/tests/psyche_download_e2e.rs +++ b/crates/spt/tests/psyche_download_e2e.rs @@ -63,8 +63,6 @@ fn clean_env(cmd: &mut Command) -> &mut Command { .env_remove("SPT_ENDPOINT_ID") } - - // [int->REQ-RESUME-CONTEXT-PULL] // [unit->REQ-TEST-RIG-DAEMON-TEARDOWN-PROVEN] this rig owns a daemon tree it // never names: pid-0 perch + scrubbed env markers so the stop is not denied, @@ -112,7 +110,11 @@ fn psyche_download_emits_brief_with_pending_then_self_clears() { ) .unwrap(); let drop_file = drops.join(format!("{id}-commune.md")); - std::fs::write(&drop_file, "\nfresh pending brief\n").unwrap(); + std::fs::write( + &drop_file, + "\nfresh pending brief\n", + ) + .unwrap(); let spt_bin = PathBuf::from(env!("CARGO_BIN_EXE_spt")); let run = || { @@ -144,7 +146,10 @@ fn psyche_download_emits_brief_with_pending_then_self_clears() { // ── LEG 1: with a present drop ── let out = run(); let stdout = String::from_utf8_lossy(&out.stdout).to_string(); - eprintln!("=== W5 psyche-download (pending) ===\nstatus={}\n{stdout}", out.status); + eprintln!( + "=== W5 psyche-download (pending) ===\nstatus={}\n{stdout}", + out.status + ); // PRESENTATION-ONLY: sampled HERE, before leg 2 removes the file, because // the claim is about what the READ did — asserting `exists()` after the // teardown would be asserting about leg 2's `remove_file`. @@ -174,10 +179,23 @@ fn psyche_download_emits_brief_with_pending_then_self_clears() { reap::reap_breadcrumb_daemon("psyche_download", home.path(), &spt_bin, observed); // ══ LEG 1's CLAIMS ═════════════════════════════════════════════════════ - assert!(out.status.success(), "psyche-download must succeed (auth ok): {:?}", out); - assert!(stdout.contains("durable live mind"), "durable emitted"); - assert!(stdout.contains(""), "present drop surfaces as "); - assert!(stdout.contains("fresh pending brief"), "the drop body rides verbatim"); + assert!( + out.status.success(), + "psyche-download must succeed (auth ok): {:?}", + out + ); + assert!( + stdout.contains("durable live mind"), + "durable emitted" + ); + assert!( + stdout.contains(""), + "present drop surfaces as " + ); + assert!( + stdout.contains("fresh pending brief"), + "the drop body rides verbatim" + ); let live_at = stdout.find("").unwrap(); let pend_at = stdout.find("").unwrap(); assert!(live_at < pend_at, "pending appends AFTER the durable tier"); @@ -188,7 +206,10 @@ fn psyche_download_emits_brief_with_pending_then_self_clears() { // ══ LEG 2's CLAIMS ═════════════════════════════════════════════════════ assert!(out2.status.success()); - assert!(stdout2.contains("durable live mind"), "durable brief still emitted"); + assert!( + stdout2.contains("durable live mind"), + "durable brief still emitted" + ); assert!( !stdout2.contains(""), "after the drop is ingested the pending slice self-clears (no duplication)" diff --git a/crates/spt/tests/psyche_sid_custody_e2e.rs b/crates/spt/tests/psyche_sid_custody_e2e.rs index 90cff592..b2ea2b90 100644 --- a/crates/spt/tests/psyche_sid_custody_e2e.rs +++ b/crates/spt/tests/psyche_sid_custody_e2e.rs @@ -36,10 +36,10 @@ use common::reap; use common::CommandNoWindowExt; use spt_daemon::{BrainLifecycle, DaemonConfig, PsycheOutcome}; +use spt_runtime::Manifest; use spt_store::info::{self, InfoJson}; use spt_store::liveness::STATUS_ONLINE; use spt_store::perch::{self, ParentHint}; -use spt_runtime::Manifest; fn start_inproc_daemon() { let reg = std::sync::Arc::new(spt_daemon::SeedRegistry::new()); @@ -56,8 +56,6 @@ fn start_inproc_daemon() { panic!("in-process seed daemon did not come up"); } - - fn wait_until(bound: Duration, mut pred: impl FnMut() -> bool) -> bool { let deadline = Instant::now() + bound; while Instant::now() < deadline { @@ -104,7 +102,13 @@ fn proof_manifest_toml(resume_cmd: &str) -> String { fn seed_bound_perch(id: &str, session_id: &str) { let path = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&path).unwrap(); - let mut rec = InfoJson::new(id, "2026-06-01T00:00:00Z", std::process::id(), session_id, "live_agent"); + let mut rec = InfoJson::new( + id, + "2026-06-01T00:00:00Z", + std::process::id(), + session_id, + "live_agent", + ); rec.status = Some(STATUS_ONLINE.to_string()); rec.controllable = Some(true); info::write_info(&path, &rec).unwrap(); @@ -160,11 +164,17 @@ fn psyche_sid_survives_parent_boundary() { "the psyche_resume role wrote the proof file (RED if the turn is neutered)" ); let uuid1 = std::fs::read_to_string(&proof).unwrap().trim().to_string(); - assert_ne!(uuid1, sid1, "the psyche's own sid is NOT the parent's (the W1 custody bug)"); - assert_eq!(uuid1.len(), 36, "the psyche sid is a canonical UUID: {uuid1:?}"); + assert_ne!( + uuid1, sid1, + "the psyche's own sid is NOT the parent's (the W1 custody bug)" + ); + assert_eq!( + uuid1.len(), + 36, + "the psyche sid is a canonical UUID: {uuid1:?}" + ); assert!( - custody.exists() - && std::fs::read_to_string(&custody).unwrap().contains(&uuid1), + custody.exists() && std::fs::read_to_string(&custody).unwrap().contains(&uuid1), "the minted psyche sid is persisted to the nested custody record" ); // The custody record is NOT an info.json → invisible to the perch instance scans. @@ -180,16 +190,26 @@ fn psyche_sid_survives_parent_boundary() { let mut cmd = Command::new(&spt_bin); cmd.no_window() .args([ - "api", "--adapter", "dummyharness", "--manifest", &mp, - "boundary", "clear", id, "--to-session-id", sid2, "--session-id", sid1, + "api", + "--adapter", + "dummyharness", + "--manifest", + &mp, + "boundary", + "clear", + id, + "--to-session-id", + sid2, + "--session-id", + sid1, ]) .env("SPT_HOME", home.path()) .env_remove("OWL_SESSION_ID"); common::output_bounded(cmd, Duration::from_secs(60)) }; let b_err = String::from_utf8_lossy(&boundary.stderr).to_string(); - let sid_after = info::read_info(&perch::resolve_perch_path(id, ParentHint::Infer)) - .map(|r| r.session_id); + let sid_after = + info::read_info(&perch::resolve_perch_path(id, ParentHint::Infer)).map(|r| r.session_id); let custody_after = std::fs::read_to_string(&custody).ok(); eprintln!( "=== F030 W2 DIAGNOSTIC: boundary_exit={:?} parent_sid_after={sid_after:?} \ @@ -204,7 +224,11 @@ fn psyche_sid_survives_parent_boundary() { reap::reap_breadcrumb_daemon("psyche_sid_custody", home.path(), &spt_bin, None); assert!(boundary.status.success(), "boundary must succeed:\n{b_err}"); - assert_eq!(sid_after.as_deref(), Some(sid2), "the boundary rotated the PARENT sid"); + assert_eq!( + sid_after.as_deref(), + Some(sid2), + "the boundary rotated the PARENT sid" + ); // The custody record is byte-for-byte untouched by the parent boundary. assert_eq!( spt_store::psyche_custody::read_psyche_sid(&psyche_perch).as_deref(), diff --git a/crates/spt/tests/rc_attach_truth.rs b/crates/spt/tests/rc_attach_truth.rs index 824746b0..034e6e18 100644 --- a/crates/spt/tests/rc_attach_truth.rs +++ b/crates/spt/tests/rc_attach_truth.rs @@ -50,8 +50,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - fn ready_pid(path: &Path) -> Option { let s = std::fs::read_to_string(path).ok()?; serde_json::from_str::(&s) @@ -72,14 +70,14 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - /// Seed `names` as subnets this node is a member of (single name → auto-home, /// keeping the focus on the attach truth under test). fn seed_subnets(names: &[&str]) { let mut store = spt_store::subnet::SubnetStore::load(); for n in names { - store.create_subnet(n, spt_store::access::Mode::Open).expect("seed subnet"); + store + .create_subnet(n, spt_store::access::Mode::Open) + .expect("seed subnet"); } store.save().expect("save subnets"); } @@ -103,7 +101,13 @@ fn register_harness(home: &Path, spt_bin: &Path, mock: &Path, name: &str, mode: /// Register a harness adapter with a RAW `[session.self]` command — the zombie /// rig's entry (a wrapper command that survives its client's death). -fn register_raw_harness(home: &Path, spt_bin: &Path, name: &str, self_cmd: &str, exe_suffix: String) { +fn register_raw_harness( + home: &Path, + spt_bin: &Path, + name: &str, + self_cmd: &str, + exe_suffix: String, +) { let src = perch::spt_home().join("srcs").join(name); std::fs::create_dir_all(&src).unwrap(); let psyche_bin = src.join(format!("psychebin{exe_suffix}")); @@ -150,7 +154,14 @@ fn spawn_broker(home: &Path, spt_bin: &Path) -> (Child, u32, PathBuf) { /// `{id}-psyche` for EVERY endpoint the test started. Never machine-wide /// (shared runner) — which is why `ids` is a list rather than the caller /// hand-rolling a second teardown that can drift from this one. -fn reap(home: &Path, spt_bin: &Path, broker: &mut Child, brain_pid: u32, extra: &[u32], ids: &[&str]) { +fn reap( + home: &Path, + spt_bin: &Path, + broker: &mut Child, + brain_pid: u32, + extra: &[u32], + ids: &[&str], +) { for p in extra { kill_pid(*p); } @@ -163,7 +174,9 @@ fn reap(home: &Path, spt_bin: &Path, broker: &mut Child, brain_pid: u32, extra: } let _ = { let mut cmd = Command::new(spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home); common::output_bounded(cmd, Duration::from_secs(20)) }; kill_pid(brain_pid); @@ -175,7 +188,11 @@ fn reap(home: &Path, spt_bin: &Path, broker: &mut Child, brain_pid: u32, extra: fn wait_status(perch_path: &Path, want: &str, budget: Duration) -> bool { let deadline = Instant::now() + budget; while Instant::now() < deadline { - if spt_store::info::read_info(perch_path).and_then(|i| i.status).as_deref() == Some(want) { + if spt_store::info::read_info(perch_path) + .and_then(|i| i.status) + .as_deref() + == Some(want) + { return true; } std::thread::sleep(Duration::from_millis(120)); @@ -295,7 +312,10 @@ fn offline_row_over_live_session_attaches() { std::env::set_var("SPT_HOME", home.path()); let spt_bin = PathBuf::from(env!("CARGO_BIN_EXE_spt")); let mock = common::sibling_bin("mock-session"); - assert!(mock.exists(), "build the dummy harness: cargo build -p mock-adapter --bin mock-session"); + assert!( + mock.exists(), + "build the dummy harness: cargo build -p mock-adapter --bin mock-session" + ); seed_subnets(&["solo"]); register_harness(home.path(), &spt_bin, &mock, "holdharness", "hold-unbound"); @@ -305,18 +325,35 @@ fn offline_row_over_live_session_attaches() { let run = run_start(home.path(), &spt_bin, "holdharness", id); let perch_path = perch::resolve_perch_path(id, ParentHint::Infer); let harness_pid = harness_pid_of(&String::from_utf8_lossy(&run.stderr)); - let was_unbound = - wait_status(&perch_path, spt_store::liveness::STATUS_UNBOUND, Duration::from_secs(15)); + let was_unbound = wait_status( + &perch_path, + spt_store::liveness::STATUS_UNBOUND, + Duration::from_secs(15), + ); // Hand-stamp the organic contradiction: offline row over the live session. spt_store::info::set_status(&perch_path, spt_store::liveness::STATUS_OFFLINE).unwrap(); let (captured, rc_stderr, saw_tick) = rc_attach_capture(home.path(), &spt_bin, id, &[]); let brain_stderr = common::daemon_stderr_panel(&brain_log); - reap(home.path(), &spt_bin, &mut broker, brain_pid, harness_pid.as_slice(), &[id]); + reap( + home.path(), + &spt_bin, + &mut broker, + brain_pid, + harness_pid.as_slice(), + &[id], + ); - assert!(run.status.success(), "hold-unbound run: {}", String::from_utf8_lossy(&run.stderr)); - assert!(was_unbound, "precondition: the skeleton reads UNBOUND before the stamp.\n{brain_stderr}"); + assert!( + run.status.success(), + "hold-unbound run: {}", + String::from_utf8_lossy(&run.stderr) + ); + assert!( + was_unbound, + "precondition: the skeleton reads UNBOUND before the stamp.\n{brain_stderr}" + ); assert!( !captured.contains("is offline — nothing to attach to"), "the offline fast-fail must NOT fire over an honest live session.\n=== rc stdout ===\n{captured}" @@ -352,13 +389,16 @@ fn offline_row_with_no_session_refuses() { let id = "ghost1"; let perch_path = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&perch_path).unwrap(); - let rec = spt_store::info::InfoJson::new(id, "2026-07-18T00:00:00Z", 4242, "sid-x", "live_agent"); + let rec = + spt_store::info::InfoJson::new(id, "2026-07-18T00:00:00Z", 4242, "sid-x", "live_agent"); spt_store::info::write_info(&perch_path, &rec).unwrap(); spt_store::info::set_status(&perch_path, spt_store::liveness::STATUS_OFFLINE).unwrap(); let out = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["rc", id]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["rc", id]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; reap(home.path(), &spt_bin, &mut broker, brain_pid, &[], &[id]); @@ -392,7 +432,13 @@ fn zombie_claim_refuses_never_attaches() { let self_cmd = "cmd /c \"ping -n 3 127.0.0.1 >nul & pause\""; #[cfg(unix)] let self_cmd = "sh -c \"sleep 2; read x\""; - register_raw_harness(home.path(), &spt_bin, "zombieharness", self_cmd, String::new()); + register_raw_harness( + home.path(), + &spt_bin, + "zombieharness", + self_cmd, + String::new(), + ); let (mut broker, brain_pid, brain_log) = spawn_broker(home.path(), &spt_bin); let id = "zomb1"; @@ -414,10 +460,24 @@ fn zombie_claim_refuses_never_attaches() { }; let wrapper_alive_post = harness_pid.is_some_and(spt_store::proc::is_process_alive); let brain_stderr = common::daemon_stderr_panel(&brain_log); - reap(home.path(), &spt_bin, &mut broker, brain_pid, harness_pid.as_slice(), &[id]); + reap( + home.path(), + &spt_bin, + &mut broker, + brain_pid, + harness_pid.as_slice(), + &[id], + ); - assert!(run.status.success(), "zombie-shape run: {}", String::from_utf8_lossy(&run.stderr)); - assert!(wrapper_alive_pre, "precondition: the wrapper survives its client chain.\n{brain_stderr}"); + assert!( + run.status.success(), + "zombie-shape run: {}", + String::from_utf8_lossy(&run.stderr) + ); + assert!( + wrapper_alive_pre, + "precondition: the wrapper survives its client chain.\n{brain_stderr}" + ); let stdout = String::from_utf8_lossy(&out.stdout); assert!( stdout.contains("defunct session"), @@ -458,7 +518,11 @@ fn resume_never_bound_reads_unbound_and_attaches() { let perch_path = perch::resolve_perch_path(id, ParentHint::Infer); let run1 = run_start(home.path(), &spt_bin, "dummyharness", id); let pid1 = harness_pid_of(&String::from_utf8_lossy(&run1.stderr)); - let online = wait_status(&perch_path, spt_store::liveness::STATUS_ONLINE, Duration::from_secs(20)); + let online = wait_status( + &perch_path, + spt_store::liveness::STATUS_ONLINE, + Duration::from_secs(20), + ); // Kill the harness (the natural death path — the field shape's launchpad): // the broker's death observers reap the session and terminal-normalize the @@ -466,7 +530,11 @@ fn resume_never_bound_reads_unbound_and_attaches() { if let Some(p) = pid1 { kill_pid(p); } - let offline = wait_status(&perch_path, spt_store::liveness::STATUS_OFFLINE, Duration::from_secs(20)); + let offline = wait_status( + &perch_path, + spt_store::liveness::STATUS_OFFLINE, + Duration::from_secs(20), + ); // RESUME into a never-binding harness: the pre-bind window is permanent. // @@ -480,17 +548,35 @@ fn resume_never_bound_reads_unbound_and_attaches() { let pid2 = harness_pid_of(&String::from_utf8_lossy(&run2.stderr)); // THE writer-truth assert: the resumed-but-never-bound perch reads UNBOUND, // not offline (pre-fix: stayed offline forever). - let unbound = wait_status(&perch_path, spt_store::liveness::STATUS_UNBOUND, Duration::from_secs(15)); + let unbound = wait_status( + &perch_path, + spt_store::liveness::STATUS_UNBOUND, + Duration::from_secs(15), + ); let (captured, rc_stderr, saw_tick) = rc_attach_capture(home.path(), &spt_bin, id, &[]); let brain_stderr = common::daemon_stderr_panel(&brain_log); let extra: Vec = pid1.into_iter().chain(pid2).collect(); reap(home.path(), &spt_bin, &mut broker, brain_pid, &extra, &[id]); - assert!(run1.status.success(), "bind bringup: {}", String::from_utf8_lossy(&run1.stderr)); - assert!(online, "precondition: the dummy binds ONLINE.\n{brain_stderr}"); - assert!(offline, "precondition: the harness death lands the offline row.\n{brain_stderr}"); - assert!(run2.status.success(), "resume launch: {}", String::from_utf8_lossy(&run2.stderr)); + assert!( + run1.status.success(), + "bind bringup: {}", + String::from_utf8_lossy(&run1.stderr) + ); + assert!( + online, + "precondition: the dummy binds ONLINE.\n{brain_stderr}" + ); + assert!( + offline, + "precondition: the harness death lands the offline row.\n{brain_stderr}" + ); + assert!( + run2.status.success(), + "resume launch: {}", + String::from_utf8_lossy(&run2.stderr) + ); assert!( unbound, "a resuming perch must read UNBOUND (not offline) through the pre-bind window.\n\ @@ -524,15 +610,22 @@ fn harness_only_refuses_truthfully_pre_stream() { let local_id = "hh1"; let perch_path = perch::resolve_perch_path(local_id, ParentHint::Infer); std::fs::create_dir_all(&perch_path).unwrap(); - let mut rec = - spt_store::info::InfoJson::new(local_id, "2026-07-18T00:00:00Z", 4242, "sid-h", "live_agent"); + let mut rec = spt_store::info::InfoJson::new( + local_id, + "2026-07-18T00:00:00Z", + 4242, + "sid-h", + "live_agent", + ); rec.controllable = Some(false); spt_store::info::write_info(&perch_path, &rec).unwrap(); spt_store::info::set_status(&perch_path, spt_store::liveness::STATUS_ONLINE).unwrap(); let local_out = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["rc", local_id]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["rc", local_id]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; @@ -561,18 +654,34 @@ fn harness_only_refuses_truthfully_pre_stream() { ); let reg_dir = perch::identity_dir().join("registry"); std::fs::create_dir_all(®_dir).unwrap(); - std::fs::write(reg_dir.join("solo.json"), serde_json::to_string(®).unwrap()).unwrap(); + std::fs::write( + reg_dir.join("solo.json"), + serde_json::to_string(®).unwrap(), + ) + .unwrap(); let remote_out = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["rc", remote_id]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["rc", remote_id]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; - reap(home.path(), &spt_bin, &mut broker, brain_pid, &[], &[local_id]); + reap( + home.path(), + &spt_bin, + &mut broker, + brain_pid, + &[], + &[local_id], + ); for (label, out) in [("local", &local_out), ("remote", &remote_out)] { let stdout = String::from_utf8_lossy(&out.stdout); - assert!(out.status.success(), "{label}: the preflight refusal is a clean exit"); + assert!( + out.status.success(), + "{label}: the preflight refusal is a clean exit" + ); assert!( stdout.contains("harness-hosted"), "{label}: the refusal names the actual state.\n=== rc stdout ===\n{stdout}" @@ -588,7 +697,6 @@ fn harness_only_refuses_truthfully_pre_stream() { } } - // ── 6. rc owns its display: NO pump diagnostic interleaves it ─────────────── // // [int->REQ-RC-DISPLAY-SOLE-WRITER] @@ -619,7 +727,10 @@ fn rc_owned_display_carries_no_pump_diagnostics() { std::env::set_var("SPT_HOME", home.path()); let spt_bin = PathBuf::from(env!("CARGO_BIN_EXE_spt")); let mock = common::sibling_bin("mock-session"); - assert!(mock.exists(), "build the dummy harness: cargo build -p mock-adapter --bin mock-session"); + assert!( + mock.exists(), + "build the dummy harness: cargo build -p mock-adapter --bin mock-session" + ); seed_subnets(&["solo"]); register_harness(home.path(), &spt_bin, &mock, "soleharness", "hold-unbound"); @@ -670,14 +781,24 @@ fn rc_owned_display_carries_no_pump_diagnostics() { let default_id = "sole-default"; let probe_run = run_start(home.path(), &spt_bin, "soleharness", probe_id); let default_start = run_start(home.path(), &spt_bin, "soleharness", default_id); - let mut harness_pids: Vec = - harness_pid_of(&String::from_utf8_lossy(&probe_run.stderr)).into_iter().collect(); - harness_pids.extend(harness_pid_of(&String::from_utf8_lossy(&default_start.stderr))); + let mut harness_pids: Vec = harness_pid_of(&String::from_utf8_lossy(&probe_run.stderr)) + .into_iter() + .collect(); + harness_pids.extend(harness_pid_of(&String::from_utf8_lossy( + &default_start.stderr, + ))); let probe = attach_and_capture(probe_id, true); let default_run = attach_and_capture(default_id, false); - reap(home.path(), &spt_bin, &mut broker, brain_pid, &harness_pids, &[probe_id, default_id]); + reap( + home.path(), + &spt_bin, + &mut broker, + brain_pid, + &harness_pids, + &[probe_id, default_id], + ); let brain_stderr = common::daemon_stderr_panel(&brain_log); for (label, run) in [("probe", &probe_run), ("default", &default_start)] { diff --git a/crates/spt/tests/ready_resume_ledger_e2e.rs b/crates/spt/tests/ready_resume_ledger_e2e.rs index 7a23cc39..c1d51719 100644 --- a/crates/spt/tests/ready_resume_ledger_e2e.rs +++ b/crates/spt/tests/ready_resume_ledger_e2e.rs @@ -154,8 +154,7 @@ fn ready_bind_ledgers_and_reconcile_hosts_no_psyche() { StartReason::Cold, ); let hosted = set.len(); - let psyche_perch = - perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); + let psyche_perch = perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); let psyche_appeared = spt_store::info::read_info(&psyche_perch).is_some(); eprintln!( diff --git a/crates/spt/tests/release_verify_e2e.rs b/crates/spt/tests/release_verify_e2e.rs index 98769685..d7c78a10 100644 --- a/crates/spt/tests/release_verify_e2e.rs +++ b/crates/spt/tests/release_verify_e2e.rs @@ -65,7 +65,10 @@ fn published_release_verifies_against_embedded_anchor() { ]) .status() .expect("run gh (installed + authed on the release-e2e runner)"); - assert!(st.success(), "gh release download {asset} from {repo}@{tag}"); + assert!( + st.success(), + "gh release download {asset} from {repo}@{tag}" + ); let dest = tmp.path().join(asset); let raw = std::fs::read_to_string(&dest).unwrap(); diff --git a/crates/spt/tests/resident_service_e2e.rs b/crates/spt/tests/resident_service_e2e.rs index 522de7a5..1e8ee2a8 100644 --- a/crates/spt/tests/resident_service_e2e.rs +++ b/crates/spt/tests/resident_service_e2e.rs @@ -83,15 +83,17 @@ fn wait_until(budget: Duration, mut pred: impl FnMut() -> bool) -> bool { pred() } - - /// A bound, offline perch (pid 0, so it is never an ancestry candidate): a /// `spt send` to it spools locally and the spooled row's `from` column is /// readable. Both the sender identity under test and the inbox are these. fn make_perch(id: &str) -> PathBuf { let path = perch::resolve_perch_path(id, ParentHint::Infer); std::fs::create_dir_all(&path).unwrap(); - info::write_info(&path, &InfoJson::new(id, "0", 0, &format!("sid-{id}"), "gateway")).unwrap(); + info::write_info( + &path, + &InfoJson::new(id, "0", 0, &format!("sid-{id}"), "gateway"), + ) + .unwrap(); path } @@ -116,8 +118,11 @@ fn stage_adapter(home: &Path, name: &str, manifest: &str, bins: &[(&Path, &str)] let src = home.join("srcs").join(name); std::fs::create_dir_all(&src).unwrap(); for (from, to) in bins { - std::fs::copy(from, src.join(format!("{to}{}", std::env::consts::EXE_SUFFIX))) - .unwrap_or_else(|e| panic!("stage {to} for {name}: {e}")); + std::fs::copy( + from, + src.join(format!("{to}{}", std::env::consts::EXE_SUFFIX)), + ) + .unwrap_or_else(|e| panic!("stage {to} for {name}: {e}")); } std::fs::write(src.join("manifest.toml"), manifest).unwrap(); src @@ -126,7 +131,10 @@ fn stage_adapter(home: &Path, name: &str, manifest: &str, bins: &[(&Path, &str)] /// `(pid, generation)` out of `brain.ready` — the daemon-is-really-up signal. fn brain_ready(path: &Path) -> Option<(u32, u64)> { let v: serde_json::Value = serde_json::from_str(&std::fs::read_to_string(path).ok()?).ok()?; - Some((v.get("pid")?.as_u64()? as u32, v.get("generation")?.as_u64()?)) + Some(( + v.get("pid")?.as_u64()? as u32, + v.get("generation")?.as_u64()?, + )) } #[test] @@ -204,7 +212,9 @@ fn a_declared_service_rises_with_the_daemon_and_reaches_the_cli() { .expect("spawn spt daemon run"); let broker_pid = broker.id(); let ready_path = home.path().join("brain.ready"); - let daemon_up = wait_until(Duration::from_secs(45), || brain_ready(&ready_path).is_some()); + let daemon_up = wait_until(Duration::from_secs(45), || { + brain_ready(&ready_path).is_some() + }); // The population sweep's ancestry seeds, pinned HERE — while both are // provably ours — because that is the only moment they can be. Teardown @@ -242,7 +252,8 @@ fn a_declared_service_rises_with_the_daemon_and_reaches_the_cli() { ); std::fs::read_to_string(&path).unwrap_or_default() }; - let mock_env = std::fs::read_to_string(service_dir("svcboot").join("mock-env")).unwrap_or_default(); + let mock_env = + std::fs::read_to_string(service_dir("svcboot").join("mock-env")).unwrap_or_default(); let spooled: Vec<(i64, String, String)> = spt_store::spool::peek_all_at(&inbox) .unwrap_or_default() .into_iter() @@ -392,7 +403,10 @@ fn a_declared_service_rises_with_the_daemon_and_reaches_the_cli() { ("resident/rel", rel_service_pid, &rel_exe, rel_obs), ] { if let Some(pid) = pid { - verdicts.push((label, reap::authenticated_kill(label, pid, expected, observed))); + verdicts.push(( + label, + reap::authenticated_kill(label, pid, expected, observed), + )); } } if let Some(brain) = brain_seed.or_else(|| brain_ready(&ready_path).map(|(pid, _)| pid)) { @@ -450,7 +464,10 @@ fn a_declared_service_rises_with_the_daemon_and_reaches_the_cli() { notice is contract, not courtesy, and its absence leaves the operator \ believing something is running: {add_offline_err}" ); - assert!(daemon_up, "PRECONDITION: the daemon never came up.\n{daemon_stderr}"); + assert!( + daemon_up, + "PRECONDITION: the daemon never came up.\n{daemon_stderr}" + ); assert!( boot_alive, "REQ-RESIDENT-SERVICE: a `start = \"boot\"` service is desired-state-running \ @@ -502,7 +519,10 @@ fn a_declared_service_rises_with_the_daemon_and_reaches_the_cli() { declared service through the reconcile nudge and say so per option — \ installing an adapter never requires restarting spt: {add_live_err}" ); - assert!(rel_started, "and the service must really be running.\n{daemon_stderr}"); + assert!( + rel_started, + "and the service must really be running.\n{daemon_stderr}" + ); assert!( broker_survived, "the nudged daemon is the SAME process (pid {broker_pid}) — a service that \ diff --git a/crates/spt/tests/resume_no_control_steal_e2e.rs b/crates/spt/tests/resume_no_control_steal_e2e.rs index 4c2da14d..291e0411 100644 --- a/crates/spt/tests/resume_no_control_steal_e2e.rs +++ b/crates/spt/tests/resume_no_control_steal_e2e.rs @@ -95,7 +95,9 @@ use std::sync::{Arc, Mutex}; use std::thread; use std::time::{Duration, Instant}; -use spt_daemon::brainproc::{ready_generation_at, supervise_brain, BrainRestart, StartReason, TrialEnv}; +use spt_daemon::brainproc::{ + ready_generation_at, supervise_brain, BrainRestart, StartReason, TrialEnv, +}; use spt_daemon::codec::{read_frame, write_frame}; use spt_daemon::endpoint::broker_socket_name; use spt_daemon::frame::{Envelope, Role}; @@ -256,7 +258,9 @@ fn spawn_ticker_controller(name: &str, endpoint: &str) -> (u64, Arc) let sid = loop { let f = read_frame(&mut c).expect("frame before spawned"); if f.kind == KIND_SPAWNED { - break serde_json::from_value::(f.payload).unwrap().session_id; + break serde_json::from_value::(f.payload) + .unwrap() + .session_id; } }; let feed = Arc::new(TickerFeed { @@ -396,8 +400,10 @@ fn brain_respawn_keeps_every_session_controller_and_still_promotes() { if Instant::now() >= baseline_deadline { teardown_panic( &stop, - &format!("PRECONDITION: session {sid} controller never received a tick — \ - the child never produced output; the rig cannot show a steal"), + &format!( + "PRECONDITION: session {sid} controller never received a tick — \ + the child never produced output; the rig cannot show a steal" + ), ); } thread::sleep(Duration::from_millis(25)); @@ -439,7 +445,10 @@ fn brain_respawn_keeps_every_session_controller_and_still_promotes() { // [pre, t0] CONTAINS the whole boot and the whole resume, so a session that gained // nothing across it froze before the brain process existed and cannot be testifying // about resume. This is a bracket, not a bound: it never relaxes an assertion. - let t_pre: Vec = sessions.iter().map(|(_, f)| f.ticks.load(Ordering::Relaxed)).collect(); + let t_pre: Vec = sessions + .iter() + .map(|(_, f)| f.ticks.load(Ordering::Relaxed)) + .collect(); let p_pre: Vec> = sessions .iter() .map(|(sid, _)| broker.session_output_seq(*sid)) @@ -502,14 +511,20 @@ fn brain_respawn_keeps_every_session_controller_and_still_promotes() { // stolen controller. deployah's a4 specimen is that ambiguity: gained=[0,15,17] // through ONE resume_sessions, where a steal displaces the SET, and session 0 was // already ~4x behind its siblings BEFORE the window opened. ── - let t0: Vec = sessions.iter().map(|(_, f)| f.ticks.load(Ordering::Relaxed)).collect(); + let t0: Vec = sessions + .iter() + .map(|(_, f)| f.ticks.load(Ordering::Relaxed)) + .collect(); let p0: Vec> = sessions .iter() .map(|(sid, _)| broker.session_output_seq(*sid)) .collect(); // ~2s ≫ the 150ms tick, so GREEN accrues ~10+ ticks; comfortably clears CI jitter. thread::sleep(Duration::from_secs(2)); - let t1: Vec = sessions.iter().map(|(_, f)| f.ticks.load(Ordering::Relaxed)).collect(); + let t1: Vec = sessions + .iter() + .map(|(_, f)| f.ticks.load(Ordering::Relaxed)) + .collect(); // BOTH producer reads bracket the SAME window as the consumer tallies, and both are // taken BEFORE the teardown below kills these children — a liveness read taken after // the reap would report every child dead and convict the rig of its own cleanup. @@ -547,7 +562,10 @@ fn brain_respawn_keeps_every_session_controller_and_still_promotes() { // ── Teardown BEFORE asserting (so a failing assert still reaps the subprocess brain + // the N ticker children). ── stop.store(true, Ordering::Relaxed); - let child_pids: Vec> = sessions.iter().map(|(sid, _)| broker.session_pid(*sid)).collect(); + let child_pids: Vec> = sessions + .iter() + .map(|(sid, _)| broker.session_pid(*sid)) + .collect(); for pid in child_pids.into_iter().flatten() { kill_pid(pid); } @@ -555,7 +573,11 @@ fn brain_respawn_keeps_every_session_controller_and_still_promotes() { let promotions = env.promotions.lock().unwrap().clone(); let rollbacks = env.rollbacks.lock().unwrap().clone(); - let gained: Vec = t0.iter().zip(&t1).map(|(a, b)| b.saturating_sub(*a)).collect(); + let gained: Vec = t0 + .iter() + .zip(&t1) + .map(|(a, b)| b.saturating_sub(*a)) + .collect(); // What the CHILD did in the same window the consumer tally measured. `None` = the // session was not in the broker at one of the two reads, which is its own story and // must never collapse into "produced nothing". @@ -603,7 +625,11 @@ fn brain_respawn_keeps_every_session_controller_and_still_promotes() { }; // What each tally did across the PRE-window [pre, t0] — the interval containing the brain // spawn, its boot and its whole resume. A session flat here froze before the brain existed. - let pre_gained: Vec = t_pre.iter().zip(&t0).map(|(a, b)| b.saturating_sub(*a)).collect(); + let pre_gained: Vec = t_pre + .iter() + .zip(&t0) + .map(|(a, b)| b.saturating_sub(*a)) + .collect(); let pre_produced: Vec> = p_pre .iter() .zip(&p0) diff --git a/crates/spt/tests/resume_template_e2e.rs b/crates/spt/tests/resume_template_e2e.rs index 704135ff..b6693e02 100644 --- a/crates/spt/tests/resume_template_e2e.rs +++ b/crates/spt/tests/resume_template_e2e.rs @@ -43,8 +43,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - fn ready_pid(path: &Path) -> Option { let s = std::fs::read_to_string(path).ok()?; serde_json::from_str::(&s) @@ -65,8 +63,6 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - /// Poll for a marker file to appear (the dummy writes it before its heartbeat /// loop), bounded. Returns its parsed `(template, cwd)` lines, or None on timeout. fn wait_for_marker(path: &Path, budget: Duration) -> Option<(String, String)> { diff --git a/crates/spt/tests/run_no_dup_session_e2e.rs b/crates/spt/tests/run_no_dup_session_e2e.rs index 96e33401..91e4efe2 100644 --- a/crates/spt/tests/run_no_dup_session_e2e.rs +++ b/crates/spt/tests/run_no_dup_session_e2e.rs @@ -40,8 +40,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - fn ready_pid(path: &Path) -> Option { let s = std::fs::read_to_string(path).ok()?; serde_json::from_str::(&s) @@ -62,8 +60,6 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - /// A headless bringup of ``: spawn+return, no attach. `verb` is the /// lifecycle verb to drive it with (`start` mints a fresh session, `resume` /// comes back on the latest ledger row) — the two INTENTS this gate's B1 and B4 @@ -109,13 +105,11 @@ fn wait_for_status(id: &str, want: &str, budget: Duration) -> bool { /// `endpoint_id` — the same `KIND_SESSIONS` map `SessionProbe::has_session` reads. /// Returns the sorted broker session ids for the endpoint (empty = none). fn broker_session_ids_for(endpoint_id: &str) -> Vec { - let mut brain = match spt_daemon::Brain::cold_start( - &spt_daemon::endpoint::broker_socket_name(), - 1, - ) { - Ok(b) => b, - Err(_) => return Vec::new(), - }; + let mut brain = + match spt_daemon::Brain::cold_start(&spt_daemon::endpoint::broker_socket_name(), 1) { + Ok(b) => b, + Err(_) => return Vec::new(), + }; let reply = match brain.sessions() { Ok(r) => r, Err(_) => return Vec::new(), @@ -184,18 +178,18 @@ fn run_over_live_endpoint_never_mints_a_second_session() { .stderr(Stdio::from(brain_log_file)) .spawn() .expect("spawn spt daemon run (broker process)"); - let brain_pid = match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(30)) - { - Some(p) => p, - None => { - let _ = broker.kill(); - let _ = broker.wait(); - panic!( - "PRECONDITION: brain never came up.\n{}", - common::daemon_stderr_panel(&brain_log) - ); - } - }; + let brain_pid = + match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(30)) { + Some(p) => p, + None => { + let _ = broker.kill(); + let _ = broker.wait(); + panic!( + "PRECONDITION: brain never came up.\n{}", + common::daemon_stderr_panel(&brain_log) + ); + } + }; // ── (4) Bring the endpoint LIVE (gen1) and prove it holds EXACTLY ONE session. ── let id = "dupguard"; @@ -253,7 +247,9 @@ fn run_over_live_endpoint_never_mints_a_second_session() { // ── (7) daemon stop (bounded). ── let stop = { let mut cmd = Command::new(&spt_bin); - cmd.no_window().args(["daemon", "stop"]).env("SPT_HOME", home.path()); + cmd.no_window() + .args(["daemon", "stop"]) + .env("SPT_HOME", home.path()); common::output_bounded(cmd, Duration::from_secs(20)) }; @@ -273,7 +269,10 @@ fn run_over_live_endpoint_never_mints_a_second_session() { // ── (8) Reap scoped: every captured harness pid + any hosted psyche + brain + // broker. Never machine-wide. ── - for p in [harness_pid1, harness_pid2, harness_pid3].into_iter().flatten() { + for p in [harness_pid1, harness_pid2, harness_pid3] + .into_iter() + .flatten() + { kill_pid(p); } let psyche_perch = perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); @@ -285,7 +284,10 @@ fn run_over_live_endpoint_never_mints_a_second_session() { let _ = broker.wait(); // ── Assertions. ── - assert!(run1.status.success(), "PRECONDITION: gen1 `endpoint start` must succeed"); + assert!( + run1.status.success(), + "PRECONDITION: gen1 `endpoint start` must succeed" + ); assert!(online, "PRECONDITION: the endpoint must come ONLINE"); assert_eq!( gen1_sessions.len(), diff --git a/crates/spt/tests/seal_shortform_e2e.rs b/crates/spt/tests/seal_shortform_e2e.rs index 256860f1..a4c769fd 100644 --- a/crates/spt/tests/seal_shortform_e2e.rs +++ b/crates/spt/tests/seal_shortform_e2e.rs @@ -35,7 +35,7 @@ mod common; use common::reap; use common::CommandNoWindowExt; -use spt_store::dispatchresults::{DispatchStatus, self as results}; +use spt_store::dispatchresults::{self as results, DispatchStatus}; use spt_store::perch::{self, ParentHint}; fn manifest_with_io(home: &Path) -> PathBuf { diff --git a/crates/spt/tests/send_stamp_agent_id_e2e.rs b/crates/spt/tests/send_stamp_agent_id_e2e.rs index 4d7b720d..dfd9b86e 100644 --- a/crates/spt/tests/send_stamp_agent_id_e2e.rs +++ b/crates/spt/tests/send_stamp_agent_id_e2e.rs @@ -107,8 +107,14 @@ fn shelled_send_stamps_endpoint_id_from_env() { std::env::remove_var("SPT_HOME"); // ── ASSERTIONS ── - assert!(ok_pos, "the perch-bound send must succeed (spooled QUEUED): {err_pos}"); - assert!(ok_neg, "the perchless send must succeed (spooled QUEUED): {err_neg}"); + assert!( + ok_pos, + "the perch-bound send must succeed (spooled QUEUED): {err_pos}" + ); + assert!( + ok_neg, + "the perchless send must succeed (spooled QUEUED): {err_neg}" + ); assert_eq!( rows.len(), 2, diff --git a/crates/spt/tests/shell_actgate_e2e.rs b/crates/spt/tests/shell_actgate_e2e.rs index a4977ff3..dd3cdadc 100644 --- a/crates/spt/tests/shell_actgate_e2e.rs +++ b/crates/spt/tests/shell_actgate_e2e.rs @@ -109,7 +109,13 @@ fn act_gate_blocks_command_until_class_scoped_grant() { // ── spawn (ungated) → online. let out = spt(&[ - "shell", "spawn", "mock-shell", "--alias", "Stick", "--owner", "doyle", + "shell", + "spawn", + "mock-shell", + "--alias", + "Stick", + "--owner", + "doyle", ]); assert!( out.status.success(), @@ -137,48 +143,85 @@ fn act_gate_blocks_command_until_class_scoped_grant() { // refuses (non-TTY ⇒ CONSENT_PENDING) and the frame NEVER spools — the // durable channel stays clean (evidence absent, the binary drained nothing). let out = spt(&[ - "shell", "cmd", "--owner", "doyle", "Stick", "attach", "busid-001", + "shell", + "cmd", + "--owner", + "doyle", + "Stick", + "attach", + "busid-001", ]); - assert!( - !out.status.success(), - "ungranted gated attach must refuse" - ); + assert!(!out.status.success(), "ungranted gated attach must refuse"); let pending = String::from_utf8_lossy(&out.stderr).to_string(); assert!( pending.contains("CONSENT_PENDING") && pending.contains("shell-act:attach"), "refused as a pending act-gate, naming the namespaced capability: {pending}" ); assert!( - std::fs::read_to_string(&evidence).map(|s| s.trim().is_empty()).unwrap_or(true), + std::fs::read_to_string(&evidence) + .map(|s| s.trim().is_empty()) + .unwrap_or(true), "the gated command must NOT spool before approval (channel stays clean)" ); // ── class scope is real: a grant for the WRONG class (`storage`) does not // authorize the `hid`-class `attach` — it still refuses. let out = spt(&[ - "grant", "add", "shell-act:attach", "doyle", "--qualifier", "storage", + "grant", + "add", + "shell-act:attach", + "doyle", + "--qualifier", + "storage", ]); - assert!(out.status.success(), "grant add (storage): {}", String::from_utf8_lossy(&out.stderr)); + assert!( + out.status.success(), + "grant add (storage): {}", + String::from_utf8_lossy(&out.stderr) + ); let out = spt(&[ - "shell", "cmd", "--owner", "doyle", "Stick", "attach", "busid-001", + "shell", + "cmd", + "--owner", + "doyle", + "Stick", + "attach", + "busid-001", ]); assert!( !out.status.success(), "a storage-class grant must not authorize a hid-class attach" ); assert!( - std::fs::read_to_string(&evidence).map(|s| s.trim().is_empty()).unwrap_or(true), + std::fs::read_to_string(&evidence) + .map(|s| s.trim().is_empty()) + .unwrap_or(true), "still no spool under the wrong-class grant" ); // ── the RIGHT-class grant (`hid`, the allow-always write) flips the same // `attach` through: it spools, the resident binary drains it, evidence lands. let out = spt(&[ - "grant", "add", "shell-act:attach", "doyle", "--qualifier", "hid", + "grant", + "add", + "shell-act:attach", + "doyle", + "--qualifier", + "hid", ]); - assert!(out.status.success(), "grant add (hid): {}", String::from_utf8_lossy(&out.stderr)); + assert!( + out.status.success(), + "grant add (hid): {}", + String::from_utf8_lossy(&out.stderr) + ); let out = spt(&[ - "shell", "cmd", "--owner", "doyle", "Stick", "attach", "busid-001", + "shell", + "cmd", + "--owner", + "doyle", + "Stick", + "attach", + "busid-001", ]); assert!( out.status.success(), @@ -206,7 +249,13 @@ fn act_gate_blocks_command_until_class_scoped_grant() { // ── a DIFFERENT gated op (`wipe`, class `storage`) is unaffected by the // attach grant — per-capability scope, not per-shell — and still refuses. let out = spt(&[ - "shell", "cmd", "--owner", "doyle", "Stick", "wipe", "everything", + "shell", + "cmd", + "--owner", + "doyle", + "Stick", + "wipe", + "everything", ]); assert!( !out.status.success(), diff --git a/crates/spt/tests/shell_hints_e2e.rs b/crates/spt/tests/shell_hints_e2e.rs index 68f929d0..01cd682a 100644 --- a/crates/spt/tests/shell_hints_e2e.rs +++ b/crates/spt/tests/shell_hints_e2e.rs @@ -152,7 +152,9 @@ fn shell_hints_reach_the_now_signal_in_both_arms() { assert!(signal.contains(""), "no HINTS block: {signal}"); // (1) instantiated → the FULL text, from an OFFLINE instance. assert!( - signal.contains("keyword hint for SPT shell adapter pacer: \"screenshot\"-->PACER captures a window"), + signal.contains( + "keyword hint for SPT shell adapter pacer: \"screenshot\"-->PACER captures a window" + ), "the instantiated adapter's full hint is missing: {signal}" ); // (2) not instantiated → the teaser, and NOT the text. diff --git a/crates/spt/tests/shell_perch_dir_e2e.rs b/crates/spt/tests/shell_perch_dir_e2e.rs index 89f82c50..00493d57 100644 --- a/crates/spt/tests/shell_perch_dir_e2e.rs +++ b/crates/spt/tests/shell_perch_dir_e2e.rs @@ -25,8 +25,6 @@ mod common; use spt_store::perch::{self, ParentHint}; - - /// In-process seed daemon on this home's seed socket (contract_e2e's pattern — /// no REAL detached `spt daemon` from this test). Leaked; dies with the test. fn start_inproc_daemon() { diff --git a/crates/spt/tests/shortform_dispatch_e2e.rs b/crates/spt/tests/shortform_dispatch_e2e.rs index 4b3658c7..0f20c334 100644 --- a/crates/spt/tests/shortform_dispatch_e2e.rs +++ b/crates/spt/tests/shortform_dispatch_e2e.rs @@ -121,7 +121,10 @@ fn a_live_tag_dispatches_only_when_the_manifest_declares_compliance() { // ── (2) THE GATE, taken FIRST so the positive arm cannot be explained by // leftover state: an undeclared adapter's ingest is none of core's // business, however live the tag is. - let out = report(&undeclared, "status update @"); + let out = report( + &undeclared, + "status update @", + ); assert!( out.status.success(), "the state call itself still succeeds: {}", @@ -151,7 +154,11 @@ fn a_live_tag_dispatches_only_when_the_manifest_declares_compliance() { "operator ruling 8: a tag inside backticks is a QUOTATION end to end, not just in \ the parser's own unit" ); - assert!(results().is_empty(), "a quotation records nothing: {:?}", results()); + assert!( + results().is_empty(), + "a quotation records nothing: {:?}", + results() + ); // ── (1) THE LIVE ARM: declared adapter, live tag ⇒ a real message lands. let body = "the build is green"; diff --git a/crates/spt/tests/translate_proof.rs b/crates/spt/tests/translate_proof.rs index 028c768c..ae1c9e45 100644 --- a/crates/spt/tests/translate_proof.rs +++ b/crates/spt/tests/translate_proof.rs @@ -122,7 +122,15 @@ fn translate_proof_drives_the_real_translation_binary() { let out = run_spt( &spt_bin, home.path(), - &["adapter", "translate-proof", "cc", "--event", event, "--session", "sessA"], + &[ + "adapter", + "translate-proof", + "cc", + "--event", + event, + "--session", + "sessA", + ], Some("nocommit"), ); let stderr = String::from_utf8_lossy(&out.stderr); @@ -218,7 +226,15 @@ fn translate_proof_dir_override_proofs_unregistered_install() { let out = run_spt( &spt_bin, home.path(), - &["adapter", "translate-proof", "dev", "--event", event, "--dir", &devdir_s], + &[ + "adapter", + "translate-proof", + "dev", + "--event", + event, + "--dir", + &devdir_s, + ], None, ); let stdout = String::from_utf8_lossy(&out.stdout); @@ -236,7 +252,15 @@ fn translate_proof_dir_override_proofs_unregistered_install() { let out = run_spt( &spt_bin, home.path(), - &["adapter", "translate-proof", "dev", "--event", event, "--manifest", &manifest_s], + &[ + "adapter", + "translate-proof", + "dev", + "--event", + event, + "--manifest", + &manifest_s, + ], None, ); let stderr = String::from_utf8_lossy(&out.stderr); diff --git a/crates/spt/tests/trial_drain_drive_e2e.rs b/crates/spt/tests/trial_drain_drive_e2e.rs index 636d1260..caf3bcd0 100644 --- a/crates/spt/tests/trial_drain_drive_e2e.rs +++ b/crates/spt/tests/trial_drain_drive_e2e.rs @@ -106,7 +106,9 @@ use std::thread; use std::time::{Duration, Instant}; use spt_daemon::brain::Brain; -use spt_daemon::brainproc::{ready_generation_at, supervise_brain, BrainRestart, StartReason, TrialEnv}; +use spt_daemon::brainproc::{ + ready_generation_at, supervise_brain, BrainRestart, StartReason, TrialEnv, +}; use spt_daemon::codec::{read_frame, write_frame}; use spt_daemon::endpoint::broker_socket_name; use spt_daemon::frame::{Envelope, Role}; @@ -378,7 +380,7 @@ fn trial_candidate_self_drives_the_reap_of_a_black_holed_old_gen_controller() { Duration::from_millis(50), env_sup.as_ref(), Duration::from_secs(60), // generous window — covers a slow-CI boot (eaten before the - // ready-latch arms) plus the self-drive reap, with margin + // ready-latch arms) plus the self-drive reap, with margin move |gen, reason: StartReason, binary| { if binary.is_some() { // A rollback spawn means the trial FAILED to promote (the RED @@ -431,7 +433,9 @@ fn trial_candidate_self_drives_the_reap_of_a_black_holed_old_gen_controller() { let sid = loop { let f = read_frame(&mut a).expect("frame before spawned"); if f.kind == KIND_SPAWNED { - break serde_json::from_value::(f.payload).unwrap().session_id; + break serde_json::from_value::(f.payload) + .unwrap() + .session_id; } }; // A parked long past the test; process-per-test exit reaps it. diff --git a/crates/spt/tests/tunnel_e2e.rs b/crates/spt/tests/tunnel_e2e.rs index c3335801..3e1ca22b 100644 --- a/crates/spt/tests/tunnel_e2e.rs +++ b/crates/spt/tests/tunnel_e2e.rs @@ -58,8 +58,9 @@ fn start_inproc_daemon(dir: &std::path::Path) { }); let host = NetHost::start(hermetic(Identity::generate())).expect("net host start"); - let broker = Broker::bind_in_with_net(&broker_socket_name(), dir.join("effects.log"), Some(host)) - .expect("bind broker with net"); + let broker = + Broker::bind_in_with_net(&broker_socket_name(), dir.join("effects.log"), Some(host)) + .expect("bind broker with net"); let serve = Arc::clone(&broker); thread::spawn(move || { let _ = serve.serve(); @@ -82,7 +83,9 @@ fn start_inproc_daemon(dir: &std::path::Path) { /// Spawn `cmd` with `input` on stdin, capture output, bounded. fn output_with_stdin(mut cmd: Command, input: Vec, deadline: Duration) -> Output { - cmd.stdin(Stdio::piped()).stdout(Stdio::piped()).stderr(Stdio::piped()); + cmd.stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); let (tx, rx) = std::sync::mpsc::channel(); thread::spawn(move || { let res = (|| { @@ -151,7 +154,14 @@ fn shell_tunnel_round_trips_opaque_bytes_through_the_real_surfaces() { let token_of = || spt_daemon::shellhost::read_link_token(&shell_perch).expect("a link token is parked"); let online_by_token = |token: &str| { - let out = spt(&["api", "--adapter", "mock-shell", "bind-shell", "--link", token]); + let out = spt(&[ + "api", + "--adapter", + "mock-shell", + "bind-shell", + "--link", + token, + ]); assert!( out.status.success(), "bind-shell: {}", @@ -165,7 +175,10 @@ fn shell_tunnel_round_trips_opaque_bytes_through_the_real_surfaces() { }; // Owner sends raw bytes into the tunnel. let owner_send = |bytes: Vec| { - let out = spt_stdin(&["shell", "tunnel", "Scout", "send", "--owner", "doyle"], bytes); + let out = spt_stdin( + &["shell", "tunnel", "Scout", "send", "--owner", "doyle"], + bytes, + ); assert!( out.status.success(), "owner tunnel send: {}", @@ -174,7 +187,16 @@ fn shell_tunnel_round_trips_opaque_bytes_through_the_real_surfaces() { }; let shell_send = |token: &str, bytes: Vec| { let out = spt_stdin( - &["api", "--adapter", "mock-shell", "tunnel", "mock-shell-0", "send", "--link", token], + &[ + "api", + "--adapter", + "mock-shell", + "tunnel", + "mock-shell-0", + "send", + "--link", + token, + ], bytes, ); assert!( @@ -189,7 +211,14 @@ fn shell_tunnel_round_trips_opaque_bytes_through_the_real_surfaces() { let mut got = Vec::new(); for _ in 0..400 { let out = spt(&[ - "api", "--adapter", "mock-shell", "tunnel", "mock-shell-0", "recv", "--link", token, + "api", + "--adapter", + "mock-shell", + "tunnel", + "mock-shell-0", + "recv", + "--link", + token, ]); got.extend_from_slice(&out.stdout); if got.len() >= want { @@ -213,15 +242,28 @@ fn shell_tunnel_round_trips_opaque_bytes_through_the_real_surfaces() { }; // ── spawn (offline) + online by token → the tunnel opens. - let out = spt(&["shell", "spawn", "mock-shell", "--alias", "Scout", "--owner", "doyle"]); - assert!(out.status.success(), "spawn: {}", String::from_utf8_lossy(&out.stderr)); + let out = spt(&[ + "shell", + "spawn", + "mock-shell", + "--alias", + "Scout", + "--owner", + "doyle", + ]); + assert!( + out.status.success(), + "spawn: {}", + String::from_utf8_lossy(&out.stderr) + ); let token_a = token_of(); online_by_token(&token_a); // A payload the envelope grammar would mangle: NULs, an ` = b"\x00not really an event\xff\xfe\x00".to_vec(); + let blob1: Vec = + b"\x00not really an event\xff\xfe\x00".to_vec(); let blob2: Vec = (0..=255u8).cycle().take(200 * 1024).collect(); let want: Vec = blob1.iter().chain(blob2.iter()).copied().collect(); @@ -229,14 +271,24 @@ fn shell_tunnel_round_trips_opaque_bytes_through_the_real_surfaces() { owner_send(blob1.clone()); owner_send(blob2.clone()); let got = shell_recv_until(&token_a, want.len()); - assert_eq!(got.len(), want.len(), "shell drained every owner→shell byte (no loss/dup)"); - assert_eq!(got, want, "owner→shell opaque bytes round-trip byte-exact, in order"); + assert_eq!( + got.len(), + want.len(), + "shell drained every owner→shell byte (no loss/dup)" + ); + assert_eq!( + got, want, + "owner→shell opaque bytes round-trip byte-exact, in order" + ); // ── (1b) shell → owner, byte-exact (the reverse leg of the duplex). let reply: Vec = b"\x00\x01\x02\xaa\xbb reply payload".to_vec(); shell_send(&token_a, reply.clone()); let back = owner_recv_until(reply.len()); - assert_eq!(back, reply, "shell→owner opaque bytes round-trip byte-exact"); + assert_eq!( + back, reply, + "shell→owner opaque bytes round-trip byte-exact" + ); // ── (2)+(3) link-break closes the tunnel, and no pre-break byte survives the // relink (R1). Send a pending payload, DON'T drain it, break the link, relink to @@ -262,7 +314,11 @@ fn shell_tunnel_round_trips_opaque_bytes_through_the_real_surfaces() { // Relink (fresh token) + online → a FRESH tunnel; the stale pre-break bytes are // never surfaced to it. let out = spt(&["shell", "relink", "Scout", "--owner", "doyle"]); - assert!(out.status.success(), "relink: {}", String::from_utf8_lossy(&out.stderr)); + assert!( + out.status.success(), + "relink: {}", + String::from_utf8_lossy(&out.stderr) + ); let token_b = token_of(); assert_ne!(token_a, token_b, "relink rotates the link token"); online_by_token(&token_b); diff --git a/crates/spt/tests/twohost_cli.rs b/crates/spt/tests/twohost_cli.rs index ab184e69..94c74983 100644 --- a/crates/spt/tests/twohost_cli.rs +++ b/crates/spt/tests/twohost_cli.rs @@ -210,8 +210,6 @@ fn rig_wait(what: &str, deadline: Duration, mut probe: impl FnMut() -> bool) { panic!("never converged on the rig: {what}"); } - - fn ready_pid(path: &Path) -> Option { let s = std::fs::read_to_string(path).ok()?; serde_json::from_str::(&s) @@ -242,8 +240,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - /// One REAL `spt daemon run` under `home`, readiness-gated on `brain.ready`, /// reaped SCOPED on drop (stop verb first, then pid kills) — a rung-assert /// panic must never leak a daemon on the shared runners. @@ -627,7 +623,8 @@ fn gated_cli_role_b() { std::fs::create_dir_all(&monics).expect("monics dir"); std::fs::write(monics.join("hertz"), "reviews tests harder than I do").expect("monic"); std::fs::write(monics.join("flynn"), "field-verifies; trust the repro").expect("monic"); - cs.commit_live(ID_FORK_SRC, "fork rung seed").expect("commit mind"); + cs.commit_live(ID_FORK_SRC, "fork rung seed") + .expect("commit mind"); // The grant: node A may FORK this endpoint — AND may DISCOVER it. // @@ -703,8 +700,12 @@ fn gated_cli_role_b() { // harness is cold — nothing resident), rest intent Suspended, and the D-2 // ledger row recording the session + adapter the revive must restore. let perch_c2 = seed_perch(ID_C2, 0, "live_agent"); - spt_daemon::resting::write_rest(&perch_c2, spt_daemon::resting::RestState::Suspended, now_ms()) - .expect("seed C-2 suspended intent"); + spt_daemon::resting::write_rest( + &perch_c2, + spt_daemon::resting::RestState::Suspended, + now_ms(), + ) + .expect("seed C-2 suspended intent"); spt_store::sessions::append( &perch_c2, &spt_store::sessions::SessionEntry { @@ -803,23 +804,31 @@ fn gated_cli_role_b() { // ── C-2 (serve side): A's qualified wake lands as the wire rest edge; the // reconcile resume leg relaunches the RECORDED adapter's [session.resume] // and the harness's own bind — never a stamp — takes status to online. - rig_wait("C-2: A's wake flipped the rest intent to Active", rig.wait, || { - spt_daemon::resting::read_rest(&perch_c2) - .map(|r| r.state == spt_daemon::resting::RestState::Active) - .unwrap_or(false) - }); + rig_wait( + "C-2: A's wake flipped the rest intent to Active", + rig.wait, + || { + spt_daemon::resting::read_rest(&perch_c2) + .map(|r| r.state == spt_daemon::resting::RestState::Active) + .unwrap_or(false) + }, + ); // The RESUME template ran (not [session.self]) with the LEDGER session id. // [int->REQ-WAKE-RESUME-LEG] - rig_wait("C-2: the [session.resume] template relaunched the harness", rig.wait, || { - resume_marker.exists() - }); + rig_wait( + "C-2: the [session.resume] template relaunched the harness", + rig.wait, + || resume_marker.exists(), + ); assert!( !self_marker.exists(), "the revive must select [session.resume], never the fresh [session.self]" ); - rig_wait("C-2: the revived harness self-bound (status online)", rig.wait, || { - info::read_info(&perch_c2).is_some_and(|i| i.status.as_deref() == Some("online")) - }); + rig_wait( + "C-2: the revived harness self-bound (status online)", + rig.wait, + || info::read_info(&perch_c2).is_some_and(|i| i.status.as_deref() == Some("online")), + ); assert_eq!( info::read_info(&perch_c2).and_then(|i| i.host_error), None, @@ -919,9 +928,11 @@ fn gated_cli_role_b() { // The barrier is A's own signal, not the store alone: `knock list` finding // nothing and `knock list` printing no prescription are different failures, // and only the signal separates them. - rig_wait("fork-pair: A's undiscoverable knock left A", rig.wait, || { - saw_signal(&rig, SIG_FORKGAP_KNOCKED) - }); + rig_wait( + "fork-pair: A's undiscoverable knock left A", + rig.wait, + || saw_signal(&rig, SIG_FORKGAP_KNOCKED), + ); // [int->REQ-KNOCK-EVIDENCE-ROUTE] rig_wait( "evidence route: the knock A could not RESOLVE us by still landed here", @@ -1093,7 +1104,9 @@ fn gated_cli_role_b() { ); access.save().expect("save node-sovereign FORK grant"); } - println!("GATED OK: fork-pair consequence stated, policy refusal and sovereign acceptance pinned"); + println!( + "GATED OK: fork-pair consequence stated, policy refusal and sovereign acceptance pinned" + ); signal(&rig, &rig.b_hex(), ID_FORKGAP, SIG_FORKGAP_OK); // ── B-3 (destructive LAST): the honest daemon bounce under A's live @@ -1222,8 +1235,10 @@ fn gated_cli_role_a() { // arrived as `cli@NODE` (operator #7) and replies bounced NO_PERCH. // [int->REQ-SELF-DETECT-PARENT-PID] let mut seen_from = String::new(); - rig_wait("E-1: B's send landed in the target spool", rig.wait, || { - match spool::peek_all_at(&perch_tgt) { + rig_wait( + "E-1: B's send landed in the target spool", + rig.wait, + || match spool::peek_all_at(&perch_tgt) { Ok(rows) => match rows.iter().find(|(_, _, body, _)| body.contains(E1_BODY)) { Some((_, from, _, _)) => { seen_from = from.clone(); @@ -1232,8 +1247,8 @@ fn gated_cli_role_a() { None => false, }, Err(_) => false, - } - }); + }, + ); assert_eq!( seen_from, ID_E1, "the from-stamp is the sender endpoint's own id (parent_pid leg), never the cli origin" @@ -1249,9 +1264,11 @@ fn gated_cli_role_a() { // whole point of making fork a control surface. A holds the grant B wrote; // the fork happens on B, where the source lives. // [int->REQ-FORK-CONTROL-SURFACE] - rig_wait("W4 fork: B's source is seeded and granted", rig.wait, || { - saw_signal(&rig, SIG_FORK_READY) - }); + rig_wait( + "W4 fork: B's source is seeded and granted", + rig.wait, + || saw_signal(&rig, SIG_FORK_READY), + ); rig_wait("W4 fork: B's source row replicated to A", rig.wait, || { instance_status(ID_FORK_SRC, &rig.b_hex()).is_some() }); @@ -1283,7 +1300,10 @@ fn gated_cli_role_a() { !fork_err.contains("FORK_UNCONFIRMED"), "the fork went unanswered: {fork_err}" ); - println!("GATED OK: W4 fork driven across the boundary — {}", fork_err.trim()); + println!( + "GATED OK: W4 fork driven across the boundary — {}", + fork_err.trim() + ); rig_wait("W4 fork: B verified the forked endpoint", rig.wait, || { saw_signal(&rig, SIG_FORK_OK) }); @@ -1346,7 +1366,10 @@ fn gated_cli_role_a() { stderr={knock_err}", out.status.code() ); - println!("GATED OK: evidence-route knock left A — {}", knock_out.trim()); + println!( + "GATED OK: evidence-route knock left A — {}", + knock_out.trim() + ); signal(&rig, &rig.a_hex(), ID_TGT, SIG_FORKGAP_KNOCKED); rig_wait( "fork-pair: B read the prescription and the consequence", @@ -1389,12 +1412,12 @@ fn gated_cli_role_a() { } }); } - let contains = |hay: &[u8], needle: &[u8]| { - hay.windows(needle.len()).any(|w| w == needle) - }; - rig_wait("B-3: pre-bounce ticker output reached the viewport", rig.wait, || { - contains(&capture.lock().unwrap(), b"tick") - }); + let contains = |hay: &[u8], needle: &[u8]| hay.windows(needle.len()).any(|w| w == needle); + rig_wait( + "B-3: pre-bounce ticker output reached the viewport", + rig.wait, + || contains(&capture.lock().unwrap(), b"tick"), + ); let pre_len = capture.lock().unwrap().len(); signal(&rig, &rig.a_hex(), ID_RC, SIG_B3_ATTACHED); @@ -1402,12 +1425,16 @@ fn gated_cli_role_a() { // must paint AFTER the pre-bounce output, and live output must resume // AFTER the banner (the reheal's ring replay), all on the captured bytes. let banner = b"Reconnecting to "; - rig_wait("B-3: the reconnect banner painted after the sever", rig.wait, || { - let cap = capture.lock().unwrap(); - cap[pre_len.min(cap.len())..] - .windows(banner.len()) - .any(|w| w == banner) - }); + rig_wait( + "B-3: the reconnect banner painted after the sever", + rig.wait, + || { + let cap = capture.lock().unwrap(); + cap[pre_len.min(cap.len())..] + .windows(banner.len()) + .any(|w| w == banner) + }, + ); let banner_end = { let cap = capture.lock().unwrap(); pre_len @@ -1417,10 +1444,14 @@ fn gated_cli_role_a() { .expect("banner offset") + banner.len() }; - rig_wait("B-3: live output resumed after the banner (reheal)", rig.wait, || { - let cap = capture.lock().unwrap(); - contains(&cap[banner_end.min(cap.len())..], b"tick") - }); + rig_wait( + "B-3: live output resumed after the banner (reheal)", + rig.wait, + || { + let cap = capture.lock().unwrap(); + contains(&cap[banner_end.min(cap.len())..], b"tick") + }, + ); println!("GATED OK: B-3 banner-then-reheal on the real remote bounce"); // Cleanup: the viewport child served its purpose (the session at B lives diff --git a/crates/spt/tests/wake_resume_bind_e2e.rs b/crates/spt/tests/wake_resume_bind_e2e.rs index 1143a0a2..24a3ef44 100644 --- a/crates/spt/tests/wake_resume_bind_e2e.rs +++ b/crates/spt/tests/wake_resume_bind_e2e.rs @@ -58,8 +58,6 @@ fn kill_pid(pid: u32) { let _ = Command::new("kill").args(["-9", &pid.to_string()]).output(); } - - fn ready_pid(path: &Path) -> Option { let s = std::fs::read_to_string(path).ok()?; serde_json::from_str::(&s) @@ -80,8 +78,6 @@ fn wait_for_ready_pid(path: &Path, budget: Duration) -> Option { None } - - /// Poll a predicate to first-true, bounded. Returns whether it ever held — the /// caller reports the LAST observation, so a timeout is a readable assertion /// rather than a hang. @@ -189,23 +185,22 @@ fn wake_on_a_suspended_agent_resumes_binds_online_and_rehosts() { .stderr(Stdio::from(brain_log_file)) .spawn() .expect("spawn spt daemon run (broker process)"); - let brain_pid = match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(30)) - { - Some(p) => p, - None => { - let _ = broker.kill(); - let _ = broker.wait(); - panic!( - "PRECONDITION: brain never came up.\n{}", - common::daemon_stderr_panel(&brain_log) - ); - } - }; + let brain_pid = + match wait_for_ready_pid(&home.path().join("brain.ready"), Duration::from_secs(30)) { + Some(p) => p, + None => { + let _ = broker.kill(); + let _ = broker.wait(); + panic!( + "PRECONDITION: brain never came up.\n{}", + common::daemon_stderr_panel(&brain_log) + ); + } + }; let id = "wakeme"; let self_perch = perch::resolve_perch_path(id, ParentHint::Infer); - let psyche_perch = - perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); + let psyche_perch = perch::resolve_perch_path(&format!("{id}-psyche"), ParentHint::Explicit(id)); let status = || spt_store::info::read_info(&self_perch).and_then(|i| i.status); let spt = |args: &[&str], budget: Duration| { let mut cmd = Command::new(&spt_bin); @@ -344,15 +339,25 @@ fn wake_on_a_suspended_agent_resumes_binds_online_and_rehosts() { // ── Preconditions: the scenario really is a suspended agent with a cold // session and something to resume FROM. ── - assert!(online_1, "PRECONDITION: the fresh bringup must bind online\n{diag}"); - assert!(self_seen, "PRECONDITION: the fresh harness ran [session.self]\n{diag}"); + assert!( + online_1, + "PRECONDITION: the fresh bringup must bind online\n{diag}" + ); + assert!( + self_seen, + "PRECONDITION: the fresh harness ran [session.self]\n{diag}" + ); assert!( ledger_sid.is_some(), "PRECONDITION: the bringup recorded a ledger row — the resume leg reads its \ session id (D-2). Without it the leg's NoResumeMaterial arm fires and this \ test would prove nothing.\n{diag}" ); - assert_eq!(suspend_code, Some(0), "PRECONDITION: suspend is accepted\n{diag}"); + assert_eq!( + suspend_code, + Some(0), + "PRECONDITION: suspend is accepted\n{diag}" + ); assert!( went_offline, "PRECONDITION: killing the harness takes the session COLD (status offline)\n{diag}" diff --git a/crates/spt/tests/worker_lifecycle_e2e.rs b/crates/spt/tests/worker_lifecycle_e2e.rs index 0182fb28..aef9786e 100644 --- a/crates/spt/tests/worker_lifecycle_e2e.rs +++ b/crates/spt/tests/worker_lifecycle_e2e.rs @@ -35,8 +35,6 @@ use common::CommandNoWindowExt; use spt_store::info::{self, InfoJson}; use spt_store::perch::{self, ParentHint}; - - /// Render every child outcome before a destructive cleanup boundary and in every /// assertion failure. A hard-killed harness cannot unwind and print its panic. fn output_diagnostic(label: &str, out: &std::process::Output) -> String { diff --git a/crates/spt/tests/worker_visibility_e2e.rs b/crates/spt/tests/worker_visibility_e2e.rs index b55798a4..35eeccfd 100644 --- a/crates/spt/tests/worker_visibility_e2e.rs +++ b/crates/spt/tests/worker_visibility_e2e.rs @@ -25,8 +25,6 @@ mod common; use common::reap; use common::CommandNoWindowExt; - - /// Reap a daemon this test's `spt` calls may have auto-started — through the /// AUTHENTICATED reaper, so a `daemon.pid` naming a freed (and possibly already /// recycled) pid is refused instead of tree-killed. diff --git a/crates/xtask/src/binedge.rs b/crates/xtask/src/binedge.rs index 5982b441..ec3351c5 100644 --- a/crates/xtask/src/binedge.rs +++ b/crates/xtask/src/binedge.rs @@ -177,7 +177,10 @@ pub fn binedge_check(args: &[String]) { bin_owner.len(), guaranteed.len() + needs.len() ); - println!(" GUARANTEED (same-pkg integration test): {}", guaranteed.len()); + println!( + " GUARANTEED (same-pkg integration test): {}", + guaranteed.len() + ); println!(" NEEDS EXPLICIT BUILD: {}", needs.len()); println!( " declared prebuilds: {}", @@ -214,7 +217,10 @@ pub fn binedge_check(args: &[String]) { let mut baseline_new = 0usize; if write_baseline { std::fs::write(root.join(BASELINE), render_baseline(&reds)).expect("write baseline"); - println!("\nwrote {BASELINE} ({} entries)", baseline_keys(&reds).len()); + println!( + "\nwrote {BASELINE} ({} entries)", + baseline_keys(&reds).len() + ); } else if use_baseline { let recorded = parse_baseline(&read_lossy(&root.join(BASELINE))); let (fresh, burned) = baseline_delta(&recorded, &reds); @@ -227,7 +233,10 @@ pub fn binedge_check(args: &[String]) { // Burned-down entries are progress, never a failure. Reporting them is // what keeps the baseline shrinking instead of ossifying into a // permitted-forever list nobody prunes. - println!(" burned down (recorded, no longer present): {}", burned.len()); + println!( + " burned down (recorded, no longer present): {}", + burned.len() + ); for (file, bin) in &burned { println!(" GONE {file} {bin} — prune it: --write-baseline"); } @@ -372,7 +381,10 @@ fn kind_name(k: TargetKind) -> &'static str { /// refuses on it, because "0 wrongly flagged" out of a set the checker can no /// longer see reads exactly like a pass. // [impl->REQ-FIXTURE-BIN-BUILD-EDGE] -pub fn same_pkg_arm<'a>(guaranteed: &'a [Site], needs: &'a [Site]) -> (Vec<&'a Site>, Vec<&'a Site>) { +pub fn same_pkg_arm<'a>( + guaranteed: &'a [Site], + needs: &'a [Site], +) -> (Vec<&'a Site>, Vec<&'a Site>) { let named = |s: &Site| SAME_PKG_FIXTURES.contains(&s.bin.as_str()); ( guaranteed.iter().filter(|s| named(s)).collect(), @@ -437,7 +449,13 @@ pub fn owning_pkg(rel: &str, pkg_dirs: &BTreeMap) -> Option String { text.replace("\r\n", "\n") .split('\n') - .map(|ln| if ln.trim_start().starts_with("//") { "" } else { ln }) + .map(|ln| { + if ln.trim_start().starts_with("//") { + "" + } else { + ln + } + }) .collect::>() .join("\n") } @@ -696,7 +714,10 @@ pub fn metadata_bins(root: &Path) -> (BTreeMap, BTreeMapREQ-FIXTURE-BIN-BUILD-EDGE] #[test] fn baseline_reds_only_on_a_new_entry_and_reports_burn_down() { - let a = site("crates/spt/tests/shell_e2e.rs", "mock-shell", "spt", TargetKind::Integration); - let b = site("crates/spt/tests/new_e2e.rs", "mock-shell", "spt", TargetKind::Integration); + let a = site( + "crates/spt/tests/shell_e2e.rs", + "mock-shell", + "spt", + TargetKind::Integration, + ); + let b = site( + "crates/spt/tests/new_e2e.rs", + "mock-shell", + "spt", + TargetKind::Integration, + ); let recorded = parse_baseline( "# comment\n\ncrates/spt/tests/shell_e2e.rs\tmock-shell\n\ crates/spt/tests/retired.rs\tcapture-player\n", @@ -978,7 +1014,10 @@ let d = format!(\"no_such_bin_d{EXE_SUFFIX}\"); consumer: Some("spt".to_string()), kind: TargetKind::Integration, }; - assert_eq!(derived_fix(&s), "cargo build -p mock-adapter --bin mock-shell"); + assert_eq!( + derived_fix(&s), + "cargo build -p mock-adapter --bin mock-shell" + ); // The load-bearing property, and the reason this is not a comparison // against a copy of the format string: the emitted command, read back by diff --git a/crates/xtask/src/binnames.rs b/crates/xtask/src/binnames.rs index dbd278a2..da0babaa 100644 --- a/crates/xtask/src/binnames.rs +++ b/crates/xtask/src/binnames.rs @@ -57,7 +57,10 @@ pub struct Collision { pub fn duplicate_bin_names(targets: &[(String, String)]) -> Vec { let mut by_name: BTreeMap<&str, Vec> = BTreeMap::new(); for (package, bin) in targets { - by_name.entry(bin.as_str()).or_default().push(package.clone()); + by_name + .entry(bin.as_str()) + .or_default() + .push(package.clone()); } by_name .into_iter() @@ -78,7 +81,9 @@ pub fn duplicate_bin_names(targets: &[(String, String)]) -> Vec { /// /// `--no-deps` keeps the question to workspace members: a registry crate's bin /// does not land in our `target//` root and cannot collide there. -pub fn workspace_bin_targets(manifest_dir: &std::path::Path) -> Result, String> { +pub fn workspace_bin_targets( + manifest_dir: &std::path::Path, +) -> Result, String> { let out = std::process::Command::new(env!("CARGO")) .args(["metadata", "--no-deps", "--format-version", "1"]) .current_dir(manifest_dir) @@ -123,7 +128,10 @@ mod tests { fn an_invented_collision_is_reported_with_both_packages() { let targets = vec![ ("spt".to_string(), "translate_proof_fixture".to_string()), - ("spt-daemon".to_string(), "translate_proof_fixture".to_string()), + ( + "spt-daemon".to_string(), + "translate_proof_fixture".to_string(), + ), ("spt".to_string(), "spt".to_string()), ]; let hits = duplicate_bin_names(&targets); diff --git a/crates/xtask/src/diskfloor.rs b/crates/xtask/src/diskfloor.rs index 85b940d0..fab796e7 100644 --- a/crates/xtask/src/diskfloor.rs +++ b/crates/xtask/src/diskfloor.rs @@ -36,7 +36,12 @@ const GIB: u64 = 1024 * 1024 * 1024; /// It is printed on EVERY run, passing or not: the point of this half is that /// "was the disk full" stays answerable after the fact, and a reading that only /// appears on refusal leaves every red already in hand uninterpretable. -pub fn preflight_line(drive: &str, free_bytes: u64, floor_bytes: u64, label: Option<&str>) -> String { +pub fn preflight_line( + drive: &str, + free_bytes: u64, + floor_bytes: u64, + label: Option<&str>, +) -> String { let mut line = format!("disk preflight: drive={drive} free_bytes={free_bytes} floor_bytes={floor_bytes}"); if let Some(label) = label { @@ -80,7 +85,10 @@ pub fn disk_floor(args: &[String]) { let free_bytes = match fs2::available_space(&path) { Ok(n) => n, Err(e) => { - eprintln!("disk-floor: cannot read free space at {}: {e}", path.display()); + eprintln!( + "disk-floor: cannot read free space at {}: {e}", + path.display() + ); std::process::exit(2); } }; @@ -168,7 +176,10 @@ mod tests { // [unit->REQ-DISK-FLOOR-PREFLIGHT] #[test] fn a_zero_floor_is_print_only_and_never_refuses() { - assert!(admits(0, 0), "print-only mode records without owning a refusal"); + assert!( + admits(0, 0), + "print-only mode records without owning a refusal" + ); assert!(admits(1, 0)); // …and it is the ONLY floor that admits a dead-empty volume: the // default arm must still refuse the same reading, or print-only mode diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index e194433b..572efb10 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -215,10 +215,7 @@ mod cli_reference_tests { #[test] fn api_standin_injects_once_at_any_depth_and_only_for_the_root_verb() { assert_eq!(help_args(&path(&["seal"])), path(&["seal"])); - assert_eq!( - help_args(&path(&["api"])), - path(&["api", "--adapter", "x"]) - ); + assert_eq!(help_args(&path(&["api"])), path(&["api", "--adapter", "x"])); assert_eq!( help_args(&path(&["api", "seal"])), path(&["api", "--adapter", "x", "seal"]) @@ -2314,7 +2311,10 @@ mod docs_token_gate_tests { assert!(tokens.contains(&"ADR-0019"), "ADR-#### flagged: {tokens:?}"); assert!(tokens.contains(&"F-011"), "F-### flagged: {tokens:?}"); assert!(tokens.contains(&"M8-W5"), "M#-W# flagged: {tokens:?}"); - assert!(tokens.contains(&"releases#237"), "releases#* flagged: {tokens:?}"); + assert!( + tokens.contains(&"releases#237"), + "releases#* flagged: {tokens:?}" + ); assert_eq!(hits.iter().find(|(_, t)| t == "REQ-KICK-1").unwrap().0, 2); assert_eq!(hits.iter().find(|(_, t)| t == "releases#237").unwrap().0, 6); } @@ -2639,7 +2639,8 @@ fn claim_trees_match(cwd_tree: &Path, pool_tree: &Path) -> bool { #[cfg(windows)] fn same_path(a: &Path, b: &Path) -> bool { - a.to_string_lossy().eq_ignore_ascii_case(&b.to_string_lossy()) + a.to_string_lossy() + .eq_ignore_ascii_case(&b.to_string_lossy()) } #[cfg(not(windows))] diff --git a/crates/xtask/src/perjob.rs b/crates/xtask/src/perjob.rs index dbecc239..5caaa849 100644 --- a/crates/xtask/src/perjob.rs +++ b/crates/xtask/src/perjob.rs @@ -404,7 +404,10 @@ fn walk_job( let missing: Vec = if workspace_built { Vec::new() } else { - need.iter().filter(|b| !built.contains(*b)).cloned().collect() + need.iter() + .filter(|b| !built.contains(*b)) + .cloned() + .collect() }; let verdict = if workspace_built { Verdict::Workspace @@ -610,7 +613,10 @@ mod tests { assert_eq!(jobs[0].1.len(), 1); let orphan = "run: cargo build\njobs:\n a:\n steps: []\n"; - assert!(parse_jobs(orphan).is_err(), "an unattributable run: refuses"); + assert!( + parse_jobs(orphan).is_err(), + "an unattributable run: refuses" + ); } // [unit->REQ-FIXTURE-BIN-PERJOB-DRIFT] @@ -645,7 +651,10 @@ jobs: assert_eq!(found[0].verb, "nextest run"); assert_eq!(found[0].args, " -p spt --test x "); // `nextest run` must not be read as the shorter `test` verb. - assert_eq!(cargo_invocations("cargo +nightly build --workspace")[0].verb, "build"); + assert_eq!( + cargo_invocations("cargo +nightly build --workspace")[0].verb, + "build" + ); } // [unit->REQ-FIXTURE-BIN-PERJOB-DRIFT] diff --git a/crates/xtask/src/pickaudit.rs b/crates/xtask/src/pickaudit.rs index a063e3c9..ed94285f 100644 --- a/crates/xtask/src/pickaudit.rs +++ b/crates/xtask/src/pickaudit.rs @@ -340,7 +340,15 @@ pub fn report(range: &str, lanes: &[String], rows: &[Row]) -> Vec { pub fn refusal_lines(rows: &[Row]) -> Vec { let loss = rows .iter() - .filter(|r| matches!(r, Row::Classified { verdict: Verdict::Loss, .. })) + .filter(|r| { + matches!( + r, + Row::Classified { + verdict: Verdict::Loss, + .. + } + ) + }) .count(); let unclassified = rows .iter() @@ -675,7 +683,15 @@ mod tests { // And the refusal channel carries the classes that fail, so a caller // piping stdout still sees them. - let refusals = refusal_lines(&[row(Verdict::Loss), Row::Unpaired { pick: Commit { sha: "f".into(), subject: "s".into() } }]); + let refusals = refusal_lines(&[ + row(Verdict::Loss), + Row::Unpaired { + pick: Commit { + sha: "f".into(), + subject: "s".into(), + }, + }, + ]); assert_eq!(refusals.len(), 2, "{refusals:#?}"); assert!(refusals[0].contains("FIDELITY LOSS on 1 pick(s)")); assert!(refusals[1].contains("1 pick(s) could not be classified")); @@ -757,11 +773,7 @@ mod tests { // defect, reproduced as a commit rather than as a conflict, because // what the audit measures is the RESULT of a resolution. git_ok(repo, &["checkout", "-q", "-b", "assembly", &base]); - write( - repo, - "f.rs", - "fn keep() {}\nfn added() {\n body();\n}\n", - ); + write(repo, "f.rs", "fn keep() {}\nfn added() {\n body();\n}\n"); commit_all(repo, "feat: add the block"); git_ok(repo, &["cherry-pick", &lane_notes]); write(repo, "ci.yml", "assembly only\n"); diff --git a/crates/xtask/src/spacerun.rs b/crates/xtask/src/spacerun.rs index 5280cbfa..d8d695cf 100644 --- a/crates/xtask/src/spacerun.rs +++ b/crates/xtask/src/spacerun.rs @@ -142,7 +142,10 @@ pub fn render_rust_string_literal(body: &str) -> String { // Line continuation: eat the newline and ALL leading whitespace on // the next line. This is the arm whose absence is the defect. Some('\n') => { - while chars.peek().is_some_and(|c| c.is_whitespace() && *c != '\n') { + while chars + .peek() + .is_some_and(|c| c.is_whitespace() && *c != '\n') + { chars.next(); } } @@ -151,7 +154,10 @@ pub fn render_rust_string_literal(body: &str) -> String { if chars.peek() == Some(&'\n') { chars.next(); } - while chars.peek().is_some_and(|c| c.is_whitespace() && *c != '\n') { + while chars + .peek() + .is_some_and(|c| c.is_whitespace() && *c != '\n') + { chars.next(); } } @@ -487,9 +493,15 @@ pub fn scan_source(src: &str) -> Vec { } let trimmed = line.trim_start(); let is_comment = trimmed.starts_with("//"); - let is_assertish = ["assert", "debug_assert", "expect(", "panic!", "unreachable!"] - .iter() - .any(|m| line.contains(m)); + let is_assertish = [ + "assert", + "debug_assert", + "expect(", + "panic!", + "unreachable!", + ] + .iter() + .any(|m| line.contains(m)); // A comment is one line and holds no literal to walk, so it is the only // skip that may advance by a line. if is_comment { @@ -525,9 +537,7 @@ pub fn scan_source(src: &str) -> Vec { // quote as an opening one and collect a body running to the next // quote anywhere in the file, attributing whatever spaces it swept // up to a line that never held a literal. - let char_lit = col > 0 - && bytes[col - 1] == '\'' - && bytes.get(col + 1) == Some(&'\''); + let char_lit = col > 0 && bytes[col - 1] == '\'' && bytes.get(col + 1) == Some(&'\''); if char_lit { col += 2; continue; @@ -651,7 +661,8 @@ mod tests { // renderer must not. #[test] fn a_healthy_continuation_renders_with_one_space_and_is_not_a_finding() { - let body = "KNOCK_UNCONFIRMED: {} gave no answer \\\n does not understand knocks"; + let body = + "KNOCK_UNCONFIRMED: {} gave no answer \\\n does not understand knocks"; let rendered = render_rust_string_literal(body); assert_eq!( rendered, "KNOCK_UNCONFIRMED: {} gave no answer does not understand knocks", @@ -793,7 +804,11 @@ mod tests { fn the_repaired_fork_sentence_is_refused_in_its_original_bytes() { let src = "let a = \" re-run without --delete-source to fork it, or delete the source from the node that holds it\";\n"; let findings = scan_source(src); - assert_eq!(findings.len(), 1, "the joined literal is refused: {findings:?}"); + assert_eq!( + findings.len(), + 1, + "the joined literal is refused: {findings:?}" + ); assert_eq!( findings[0].run, 18, "and the run is the source indentation that stopped being swallowed" @@ -819,7 +834,10 @@ mod tests { fn a_marked_line_is_exempt_and_an_unmarked_one_is_not() { let marked = "let t = \"col a col b\"; // spacerun-ok: padded-table — corpus fixture\n"; let unmarked = "let t = \"col a col b\";\n"; - assert!(scan_source(marked).is_empty(), "the marker exempts the site"); + assert!( + scan_source(marked).is_empty(), + "the marker exempts the site" + ); assert_eq!( scan_source(unmarked).len(), 1, diff --git a/crates/xtask/tests/bench_row_parity.rs b/crates/xtask/tests/bench_row_parity.rs index 3818ff00..e0c3cf95 100644 --- a/crates/xtask/tests/bench_row_parity.rs +++ b/crates/xtask/tests/bench_row_parity.rs @@ -254,7 +254,8 @@ fn both_ci_wraps_propagate_the_wrapped_commands_exit_code() { // flagged ok) without letting one arm answer for the other. let all = rows(); assert!( - !all.lines().any(|l| l.contains("parity-probe") && l.contains("\"ok\":true")), + !all.lines() + .any(|l| l.contains("parity-probe") && l.contains("\"ok\":true")), "a failing wrapped command was recorded as a success: {all}" ); } diff --git a/crates/xtask/tests/pool_claim.rs b/crates/xtask/tests/pool_claim.rs index a6776c33..621e1cb3 100644 --- a/crates/xtask/tests/pool_claim.rs +++ b/crates/xtask/tests/pool_claim.rs @@ -51,5 +51,8 @@ fn verb_refuses_accidental_crossing_but_admits_the_explicit_remedy_shape() { .expect("explicit foreign-pool claim writes the arriving lane identity"); assert_eq!(Path::new(&claim.owner_tree), arriving); let stderr = String::from_utf8_lossy(&admitted.stderr); - assert!(stderr.contains("foreign pool takeover requested"), "{stderr}"); + assert!( + stderr.contains("foreign pool takeover requested"), + "{stderr}" + ); } diff --git a/docs-site/src/harness-contract/api.md b/docs-site/src/harness-contract/api.md index d0bb93ae..a5a94bed 100644 --- a/docs-site/src/harness-contract/api.md +++ b/docs-site/src/harness-contract/api.md @@ -453,7 +453,9 @@ digest and diffing it. - `--after ` answers with events newer than a seq you carry yourself, the way [`endpoint digest --after`](../cli/reference.md) does. It writes no session cursor and wins over the session cursor when both are passed. This is the mode - for a `--token` caller, which has no session identity. + for a `--token` caller, which has no session identity. A cursor above the log's + head returns no events and the actual head as `cursor`, so the caller can + resume from that lower value instead of remaining blind. A poll carrying **neither** cursor is refused by name (`IO_EVENTS_NO_CURSOR`, exit 2) rather than answered with an empty poll — a cursorless poll could only @@ -465,9 +467,18 @@ and replaying a backlog into a turn-boundary hook is the cost the delta discipline exists to avoid. Poll again after the next turn and you get that turn's events. + +On the first append to a log damaged by the former sequence-reset bug, core +repairs its retained rows under the log lock: file order and payloads are kept, +and sequences are reassigned above the old global maximum. A session carrying +an old cursor therefore sees retained history **once**, bounded by the log's +1250-row retention ceiling. This is not a new emission: adapters acting on old +`COMMUNE` content must still reject frames older than their current session. + **`--limit` says when it capped.** The answer carries `more`, and the rows it deferred are the next poll's first rows — a bounded poll never silently reads as -a complete one. +a complete one. While `more` is true, `cursor` is the last event handed over; +otherwise it is the log snapshot's true head, including ignored kinds. **`--json` is the adapter shape and is emitted even when empty:** diff --git a/docs/KNOWN-HAZARDS.md b/docs/KNOWN-HAZARDS.md index 03ebe5c8..9ec6d917 100644 --- a/docs/KNOWN-HAZARDS.md +++ b/docs/KNOWN-HAZARDS.md @@ -442,6 +442,12 @@ Hard-won edge cases harvested from the sister project (`claude_skill_owl`, ~80 c - **Origin:** ADR-0018 Q3 silently assumed `current_exe()` path-string semantics; surfaced by the v0.4.1 fleet-roll `exe_hash` bytes assert (agents `todlando` + `doyle` + `deployah`, 2026-06-11). ADR-0018 Q3 amended. +### 6.13 IO event sequences never reset at a byte-window boundary + +- **Failure:** seeking 256 KiB before EOF could land inside a UTF-8 codepoint; `read_to_string` returned `InvalidData`, the tail reader answered zero, and append minted sequence 1. Nine of nine measured resets on doyle's log matched this mechanism; four perches on the box were affected (releases#277). Duplicate/reset blocks blinded high cursors and replayed old COMMUNE rows to low cursors; value-based trim also undercounted or removed newer rows. +- **Invariant:** decode tail bytes lossily only after discarding the leading row fragment; append above the global maximum. Detect non-increasing sequences, including equal adjacent values and resets hidden between a lower first and higher last row. Under the exclusive lock, repair retained rows in file order above their old maximum, preserving payloads. Retention keeps the newest rows by position, not sequence value. +- **spt-core mapping:** `spt_store::iolog::{last_seq_at, append_locked, trim_locked}` and the mechanism, repair, and position-retention regression units. Repair can replay retained history once to an old cursor; it does not make old events new. + --- ## 7. Boundary & delivery integrity (added 2026-05-31 — Stage A red-team) @@ -1033,6 +1039,7 @@ The kill-path rule above generalizes: `daemon.pid` is not authority for *"which | 6.8 | No irreversible durable-state migration before update ready-promotion (pre-ready writes stay N-1-readable) | auto-rollback / durable-state schema (ADR-0018) | | 6.10 | Phase-significant loop timing is a durable absolute-deadline grid (no per-fire write; update preserves phase, crash resets, one-shot never resets) | durable loop timing / self-update (ADR-0018 Q4) | | 6.11 | Brain respawn execs the applied bytes (canonical exe captured at broker start, not per-spawn current_exe) + promotion bytes-gate (exe_hash == artifact, else rollback) | daemon respawn path / self-update (ADR-0018 Q3) | +| 6.13 | IO event tail reads cannot mint false zero; append exceeds the global max, reset repair preserves file order, and trim retains by position | `spt_store::iolog` | | 7.1 | Local `api` mutation authenticated to endpoint | api surface / broker IPC | | 7.2 | Idempotent delivery across brain restart | broker↔brain IPC | | 7.3 | Psyche outbound captured + `from=`/target stripped + reply-to-sender / notify-to-own-user | live-Psyche driver / daemon relay (ADR-0012) | diff --git a/traceable-reqs.toml b/traceable-reqs.toml index efc170e3..dcef4441 100644 --- a/traceable-reqs.toml +++ b/traceable-reqs.toml @@ -4275,6 +4275,7 @@ requirements = [ [[groups]] name = "adapter-harness-contract" requirements = [ + "REQ-HAZARD-IOLOG-SEQ-MONOTONIC", "REQ-ADAPTER-ADD-SURFACE-ERRORS", "REQ-ADAPTER-FLOOR-ENFORCE", "REQ-ADAPTER-FLOOR-VS-STAGED-CORE", @@ -7463,6 +7464,12 @@ required_stages = [] # DEFERRED by ratification (#16, #17). Activate in the lan id = "REQ-IO-EVENT-ADAPTER-LOG" title = "ADAPTER-CONSUMABLE IO EVENTS LAND IN A PER-ENDPOINT APPEND-ONLY LOG REGISTERED AS A THIRD BUS SINK (releases#234, operator ruling 2). The funnel's claim was that a second reader costs a REGISTRATION and never a rework, and on the sink side that holds exactly as claimed — this consumer is one `bus.register` line in `default_bus`. THE READER IS FREE, THE STORE IS NOT, and this requirement is the honest half of that claim: neither existing sink writes a per-endpoint, ordered, cursorable surface — the shell-link sink spools per linked shell and the last-msg sink keeps two overwritten slots — so a delta-cursored poll needs a NEW DURABLE STORE, and that store is what this covers. EVERY ROW CARRIES ITS OWN MONOTONIC seq AS THE LINE'S KEY RATHER THAN AS A JSON FIELD: a row is `` TAB ``, so a cursor scan parses an integer prefix and never the body, and the ordering key cannot become an accident of serialization field order. THE LOG'S seq AND THE DIGEST seq ARE DIFFERENT NUMBERS AND ARE SPELLED DIFFERENTLY (`seq` versus `digest_seq`), because the digest remains the content surface that a truncated payload points at and one name for two counters is a consumer following the wrong one. THE LOG IS BOUNDED PER ENDPOINT AND TRIMMED OLDEST-FIRST so that an adapter which stops polling cannot grow it without limit; the bound is a STATED CHOICE derived from a measured event rate rather than a guessed number, and the trim is amortized against a slack so an ordinary append is not a whole-file rewrite. APPENDS ARE SERIALIZED under an exclusive advisory lock on a stable sentinel, because the daemon publishes from several edges and two racing appends must not mint a colliding seq. A SINK FAILURE IS STILL ONLY A REPORT: this store may not become the first sink whose bad day reaches the operation it observes." required_stages = ["doc", "impl", "unit"] # ACTIVATED in the delivering lane (todlando, CONDUIT W3, 2026-08-28). + +[[requirements]] +id = "REQ-HAZARD-IOLOG-SEQ-MONOTONIC" +title = "IO event log appends mint strictly above the global sequence maximum; a tail window beginning inside a UTF-8 codepoint never produces a false zero. Reset-damaged history is renumbered above its prior maximum in file order under the exclusive lock, and retention keeps the newest rows by position (releases#277)." +required_stages = ["impl", "unit"] + [[requirements]] id = "REQ-IO-EVENT-POLL-VERB" title = "spt api io-events IS THE DELTA-CURSORED POLL A HARNESS ADAPTER READS IO EVENTS THROUGH (releases#234; the operator DELEGATED the mechanics and CHOSE POLL over push). It answers with the rows the caller has not yet been shown and with nothing else. TWO CURSOR MODES OVER ONE ORDERING: `--session-id ` keeps a per-session cursor exactly as `api now-signal` keeps per-session seen-sets, and `--after ` lets a caller carry its own cursor exactly as `endpoint digest --after` already does; naming both is what keeps a stateless adapter and a session-keyed hook off two different verbs. THE CURSOR KEY IS THE AUTH SESSION ID AND NOT A SECOND FLAG BESIDE IT: the harness session is ONE identity, and a `--session` for the cursor sitting one character from a `--session-id` for the gate would be two ways to be wrong about it on a verb an adapter wires once; a token-authenticated caller has no session identity and uses `--after`. A POLL WITH NEITHER CURSOR IS REFUSED BY NAME (`IO_EVENTS_NO_CURSOR`, exit 2) RATHER THAN ANSWERED WITH SILENCE, because a caller who asked an unanswerable question must not read the answer as nothing having happened. A NEW SESSION'S FIRST POLL SEES NOTHING AND SEEDS ITS CURSOR SILENTLY — history is the digest's job, and replaying an unbounded backlog into a turn-boundary hook is the exact cost the now-signal's delta discipline exists to avoid, with EDGE_TRANSITIONS the standing precedent for seeding silently for that reason. PROVING THIS NEEDS THE SEEDED-EMPTY FIRST POLL ASSERTED BESIDE A NON-EMPTY SECOND ONE, because an assertion that the first poll is empty passes just as well against a verb that emits nothing ever. ALL SIX EMITTED KINDS ARE VISIBLE — USER_INPUT, AGENT_OUTPUT, MSG_IN, MSG_OUT, COMMUNE, COMMUNE_FAIL — and AN UNKNOWN KIND IS IGNORED RATHER THAN REFUSED, the same posture the now-signal category vocabulary takes toward a name it does not know. TOOL_USE STAYS UNEMITTED AND THIS VERB DOES NOT CHANGE THAT: measurement says the harness adapter is its natural emitter, which is a question back to deployah and then the operator and must not ride in on this verb. THE PAYLOAD BOUND IS THE 16KB CLASS WITH A truncated FLAG AND THE DIGEST POINTER, MATCHING THE SHELL FRAME AS A CHOICE AND NOT AS AN INHERITANCE — `IoEvent.payload` is deliberately unbounded at the bus layer and the cap belongs to the frame — so that one event reads identically through either transport and a consumer needing the whole body follows the pointer into the digest. THE POLL IS AUTHENTICATED THE WAY `api poll` IS, AND FOR THE SAME REASON: it hands back the session's VERBATIM user input and agent output, which is the payload class addressed to the endpoint's occupant rather than to whoever asks. This is a DELIBERATE DEPARTURE from its sibling reader `api now-signal`, which is ungated because it renders DERIVED summaries — a ten-word excerpt, a category count — and never a raw payload; the gate follows the content, not the verb family. Proof is the `--session-id` an adapter already passes to `api state`, or a capability token, so the gate costs a compliant adapter nothing."