Skip to content

Commit c7b3296

Browse files
committed
style: cargo fmt — fix CI formatting failures
Pre-existing formatting issues in anthropic.rs surfaced by CI cargo fmt check. No functional changes.
1 parent 000aed4 commit c7b3296

11 files changed

Lines changed: 251 additions & 202 deletions

File tree

ROADMAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ Priority order: P0 = blocks CI/green state, P1 = blocks integration wiring, P2 =
308308
19. **Subcommand help falls through into runtime/API path****done**: `claw doctor --help`, `claw status --help`, `claw sandbox --help`, and nested `mcp`/`skills` help are now intercepted locally without runtime/provider startup, with regression tests covering the direct CLI paths.
309309
20. **Session state classification gap (working vs blocked vs finished vs truly stale)****done**: agent manifests now derive machine states such as `working`, `blocked_background_job`, `blocked_merge_conflict`, `degraded_mcp`, `interrupted_transport`, `finished_pending_report`, and `finished_cleanable`, and terminal-state persistence records commit provenance plus derived state so downstream monitoring can distinguish quiet progress from truly idle sessions.
310310
21. **Resumed `/status` JSON parity gap** — dogfooding shows fresh `claw status --output-format json` now emits structured JSON, but resumed slash-command status still leaks through a text-shaped path in at least one dispatch path. Local CI-equivalent repro fails `rust/crates/rusty-claude-cli/tests/resume_slash_commands.rs::resumed_status_command_emits_structured_json_when_requested` with `expected value at line 1 column 1`, so resumed automation can receive text where JSON was explicitly requested. **Action:** unify fresh vs resumed `/status` rendering through one output-format contract and add regression coverage so resumed JSON output is guaranteed valid.
311-
22. **Opaque failure surface for session/runtime crashes**repeated dogfood-facing failures can currently collapse to generic wrappers like `Something went wrong while processing your request. Please try again, or use /new to start a fresh session.` without exposing whether the fault was provider auth, session corruption, slash-command dispatch, render failure, or transport/runtime panic. This blocks fast self-recovery and turns actionable clawability bugs into blind retries. **Action:** preserve a short user-safe failure class (`provider_auth`, `session_load`, `command_dispatch`, `render`, `runtime_panic`, etc.), attach a local trace/session id, and ensure operators can jump from the chat-visible error to the exact failure log quickly.
311+
22. **Opaque failure surface for session/runtime crashes****done**: `safe_failure_class()` in `error.rs` classifies all API errors into 8 user-safe classes (`provider_auth`, `provider_internal`, `provider_retry_exhausted`, `provider_rate_limit`, `provider_transport`, `provider_error`, `context_window`, `runtime_io`). `format_user_visible_api_error` in `main.rs` attaches session ID + request trace ID to every user-visible error. Coverage in `opaque_provider_wrapper_surfaces_failure_class_session_and_trace` and 3 related tests.
312312
23. **`doctor --output-format json` check-level structure gap****done**: `claw doctor --output-format json` now keeps the human-readable `message`/`report` while also emitting structured per-check diagnostics (`name`, `status`, `summary`, `details`, plus typed fields like workspace paths and sandbox fallback data), with regression coverage in `output_format_contract.rs`.
313313
24. **Plugin lifecycle init/shutdown test flakes under workspace-parallel execution** — dogfooding surfaced that `build_runtime_runs_plugin_lifecycle_init_and_shutdown` can fail under `cargo test --workspace` while passing in isolation because sibling tests race on tempdir-backed shell init script paths. This is test brittleness rather than a code-path regression, but it still destabilizes CI confidence and wastes diagnosis cycles. **Action:** isolate temp resources per test robustly (unique dirs + no shared cwd assumptions), audit cleanup timing, and add a regression guard so the plugin lifecycle test remains stable under parallel workspace execution.
314314
26. **Resumed local-command JSON parity gap****done**: direct `claw --output-format json` already had structured renderers for `sandbox`, `mcp`, `skills`, `version`, and `init`, but resumed `claw --output-format json --resume <session> /…` paths still fell back to prose because resumed slash dispatch only emitted JSON for `/status`. Resumed `/sandbox`, `/mcp`, `/skills`, `/version`, and `/init` now reuse the same JSON envelopes as their direct CLI counterparts, with regression coverage in `rust/crates/rusty-claude-cli/tests/resume_slash_commands.rs` and `rust/crates/rusty-claude-cli/tests/output_format_contract.rs`.

rust/crates/api/src/providers/anthropic.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,10 @@ impl AnthropicClient {
515515
input_tokens: u32,
516516
}
517517

518-
let request_url = format!("{}/v1/messages/count_tokens", self.base_url.trim_end_matches('/'));
518+
let request_url = format!(
519+
"{}/v1/messages/count_tokens",
520+
self.base_url.trim_end_matches('/')
521+
);
519522
let mut request_body = self.request_profile.render_json_body(request)?;
520523
strip_unsupported_beta_body_fields(&mut request_body);
521524
let response = self
@@ -528,12 +531,7 @@ impl AnthropicClient {
528531
let response = expect_success(response).await?;
529532
let body = response.text().await.map_err(ApiError::from)?;
530533
let parsed = serde_json::from_str::<CountTokensResponse>(&body).map_err(|error| {
531-
ApiError::json_deserialize(
532-
"Anthropic count_tokens",
533-
&request.model,
534-
&body,
535-
error,
536-
)
534+
ApiError::json_deserialize("Anthropic count_tokens", &request.model, &body, error)
537535
})?;
538536
Ok(parsed.input_tokens)
539537
}
@@ -597,7 +595,9 @@ fn jitter_for_base(base: Duration) -> Duration {
597595
let tick = JITTER_COUNTER.fetch_add(1, Ordering::Relaxed);
598596
// splitmix64 finalizer — mixes the low bits so large bases still see
599597
// jitter across their full range instead of being clamped to subsec nanos.
600-
let mut mixed = raw_nanos.wrapping_add(tick).wrapping_add(0x9E37_79B9_7F4A_7C15);
598+
let mut mixed = raw_nanos
599+
.wrapping_add(tick)
600+
.wrapping_add(0x9E37_79B9_7F4A_7C15);
601601
mixed = (mixed ^ (mixed >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
602602
mixed = (mixed ^ (mixed >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
603603
mixed ^= mixed >> 31;
@@ -1268,7 +1268,7 @@ mod tests {
12681268
tools: None,
12691269
tool_choice: None,
12701270
stream: false,
1271-
..Default::default()
1271+
..Default::default()
12721272
};
12731273

12741274
assert!(request.with_streaming().stream);
@@ -1464,10 +1464,14 @@ mod tests {
14641464
// temperature is kept (Anthropic supports it)
14651465
assert_eq!(body["temperature"], serde_json::json!(0.7));
14661466
// frequency_penalty and presence_penalty are removed
1467-
assert!(body.get("frequency_penalty").is_none(),
1468-
"frequency_penalty must be stripped for Anthropic");
1469-
assert!(body.get("presence_penalty").is_none(),
1470-
"presence_penalty must be stripped for Anthropic");
1467+
assert!(
1468+
body.get("frequency_penalty").is_none(),
1469+
"frequency_penalty must be stripped for Anthropic"
1470+
);
1471+
assert!(
1472+
body.get("presence_penalty").is_none(),
1473+
"presence_penalty must be stripped for Anthropic"
1474+
);
14711475
// stop is renamed to stop_sequences
14721476
assert!(body.get("stop").is_none(), "stop must be renamed");
14731477
assert_eq!(body["stop_sequences"], serde_json::json!(["\n"]));
@@ -1484,8 +1488,10 @@ mod tests {
14841488
super::strip_unsupported_beta_body_fields(&mut body);
14851489

14861490
assert!(body.get("stop").is_none());
1487-
assert!(body.get("stop_sequences").is_none(),
1488-
"empty stop should not produce stop_sequences");
1491+
assert!(
1492+
body.get("stop_sequences").is_none(),
1493+
"empty stop should not produce stop_sequences"
1494+
);
14891495
}
14901496

14911497
#[test]
@@ -1499,7 +1505,7 @@ mod tests {
14991505
tools: None,
15001506
tool_choice: None,
15011507
stream: false,
1502-
..Default::default()
1508+
..Default::default()
15031509
};
15041510

15051511
let mut rendered = client

rust/crates/api/src/providers/openai_compat.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,7 @@ impl OpenAiCompatClient {
135135
let request_id = request_id_from_headers(response.headers());
136136
let body = response.text().await.map_err(ApiError::from)?;
137137
let payload = serde_json::from_str::<ChatCompletionResponse>(&body).map_err(|error| {
138-
ApiError::json_deserialize(
139-
self.config.provider_name,
140-
&request.model,
141-
&body,
142-
error,
143-
)
138+
ApiError::json_deserialize(self.config.provider_name, &request.model, &body, error)
144139
})?;
145140
let mut normalized = normalize_response(&request.model, payload)?;
146141
if normalized.request_id.is_none() {
@@ -160,10 +155,7 @@ impl OpenAiCompatClient {
160155
Ok(MessageStream {
161156
request_id: request_id_from_headers(response.headers()),
162157
response,
163-
parser: OpenAiSseParser::with_context(
164-
self.config.provider_name,
165-
request.model.clone(),
166-
),
158+
parser: OpenAiSseParser::with_context(self.config.provider_name, request.model.clone()),
167159
pending: VecDeque::new(),
168160
done: false,
169161
state: StreamState::new(request.model.clone()),
@@ -253,7 +245,9 @@ fn jitter_for_base(base: Duration) -> Duration {
253245
.map(|elapsed| u64::try_from(elapsed.as_nanos()).unwrap_or(u64::MAX))
254246
.unwrap_or(0);
255247
let tick = JITTER_COUNTER.fetch_add(1, Ordering::Relaxed);
256-
let mut mixed = raw_nanos.wrapping_add(tick).wrapping_add(0x9E37_79B9_7F4A_7C15);
248+
let mut mixed = raw_nanos
249+
.wrapping_add(tick)
250+
.wrapping_add(0x9E37_79B9_7F4A_7C15);
257251
mixed = (mixed ^ (mixed >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
258252
mixed = (mixed ^ (mixed >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
259253
mixed ^= mixed >> 31;
@@ -1110,7 +1104,7 @@ mod tests {
11101104
tools: None,
11111105
tool_choice: None,
11121106
stream: true,
1113-
..Default::default()
1107+
..Default::default()
11141108
},
11151109
OpenAiCompatConfig::openai(),
11161110
);
@@ -1129,7 +1123,7 @@ mod tests {
11291123
tools: None,
11301124
tool_choice: None,
11311125
stream: true,
1132-
..Default::default()
1126+
..Default::default()
11331127
},
11341128
OpenAiCompatConfig::xai(),
11351129
);
@@ -1240,8 +1234,14 @@ mod tests {
12401234
..Default::default()
12411235
};
12421236
let payload = build_chat_completion_request(&request, OpenAiCompatConfig::openai());
1243-
assert!(payload.get("temperature").is_none(), "reasoning model should strip temperature");
1244-
assert!(payload.get("top_p").is_none(), "reasoning model should strip top_p");
1237+
assert!(
1238+
payload.get("temperature").is_none(),
1239+
"reasoning model should strip temperature"
1240+
);
1241+
assert!(
1242+
payload.get("top_p").is_none(),
1243+
"reasoning model should strip top_p"
1244+
);
12451245
assert!(payload.get("frequency_penalty").is_none());
12461246
assert!(payload.get("presence_penalty").is_none());
12471247
// stop is safe for all providers
@@ -1269,7 +1269,10 @@ mod tests {
12691269
..Default::default()
12701270
};
12711271
let payload = build_chat_completion_request(&request, OpenAiCompatConfig::openai());
1272-
assert!(payload.get("temperature").is_none(), "temperature should be absent");
1272+
assert!(
1273+
payload.get("temperature").is_none(),
1274+
"temperature should be absent"
1275+
);
12731276
assert!(payload.get("top_p").is_none(), "top_p should be absent");
12741277
assert!(payload.get("frequency_penalty").is_none());
12751278
assert!(payload.get("presence_penalty").is_none());

rust/crates/runtime/src/config.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -908,8 +908,10 @@ fn parse_optional_trusted_roots(root: &JsonValue) -> Result<Vec<String>, ConfigE
908908
let Some(object) = root.as_object() else {
909909
return Ok(Vec::new());
910910
};
911-
Ok(optional_string_array(object, "trustedRoots", "merged settings.trustedRoots")?
912-
.unwrap_or_default())
911+
Ok(
912+
optional_string_array(object, "trustedRoots", "merged settings.trustedRoots")?
913+
.unwrap_or_default(),
914+
)
913915
}
914916

915917
fn parse_filesystem_mode_label(value: &str) -> Result<FilesystemIsolationMode, ConfigError> {

rust/crates/runtime/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,6 @@ pub use compact::{
5656
compact_session, estimate_session_tokens, format_compact_summary,
5757
get_compact_continuation_message, should_compact, CompactionConfig, CompactionResult,
5858
};
59-
pub use config_validate::{
60-
check_unsupported_format, format_diagnostics, validate_config_file, ConfigDiagnostic,
61-
DiagnosticKind, ValidationResult,
62-
};
6359
pub use config::{
6460
ConfigEntry, ConfigError, ConfigLoader, ConfigSource, McpConfigCollection,
6561
McpManagedProxyServerConfig, McpOAuthConfig, McpRemoteServerConfig, McpSdkServerConfig,
@@ -68,17 +64,21 @@ pub use config::{
6864
RuntimeHookConfig, RuntimePermissionRuleConfig, RuntimePluginConfig, ScopedMcpServerConfig,
6965
CLAW_SETTINGS_SCHEMA_NAME,
7066
};
67+
pub use config_validate::{
68+
check_unsupported_format, format_diagnostics, validate_config_file, ConfigDiagnostic,
69+
DiagnosticKind, ValidationResult,
70+
};
7171
pub use conversation::{
7272
auto_compaction_threshold_from_env, ApiClient, ApiRequest, AssistantEvent, AutoCompactionEvent,
7373
ConversationRuntime, PromptCacheEvent, RuntimeError, StaticToolExecutor, ToolError,
7474
ToolExecutor, TurnSummary,
7575
};
76-
pub use git_context::{GitCommitEntry, GitContext};
7776
pub use file_ops::{
7877
edit_file, glob_search, grep_search, read_file, write_file, EditFileOutput, GlobSearchOutput,
7978
GrepSearchInput, GrepSearchOutput, ReadFileOutput, StructuredPatchHunk, TextFilePayload,
8079
WriteFileOutput,
8180
};
81+
pub use git_context::{GitCommitEntry, GitContext};
8282
pub use hooks::{
8383
HookAbortSignal, HookEvent, HookProgressEvent, HookProgressReporter, HookRunResult, HookRunner,
8484
};

rust/crates/runtime/src/mcp_server.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,9 +366,7 @@ mod tests {
366366
server_name: "test".to_string(),
367367
server_version: "0.0.0".to_string(),
368368
tools: Vec::new(),
369-
tool_handler: Box::new(|name, args| {
370-
Ok(format!("called {name} with {args}"))
371-
}),
369+
tool_handler: Box::new(|name, args| Ok(format!("called {name} with {args}"))),
372370
},
373371
stdin: BufReader::new(stdin()),
374372
stdout: stdout(),

rust/crates/runtime/src/prompt.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,6 @@ fn read_git_status(cwd: &Path) -> Option<String> {
253253
}
254254
}
255255

256-
257256
fn read_git_diff(cwd: &Path) -> Option<String> {
258257
let mut sections = Vec::new();
259258

@@ -715,8 +714,16 @@ mod tests {
715714
.render();
716715

717716
// then: branch, recent commits and staged files are present in context
718-
let gc = context.git_context.as_ref().expect("git context should be present");
719-
let commits: String = gc.recent_commits.iter().map(|c| c.subject.clone()).collect::<Vec<_>>().join("\n");
717+
let gc = context
718+
.git_context
719+
.as_ref()
720+
.expect("git context should be present");
721+
let commits: String = gc
722+
.recent_commits
723+
.iter()
724+
.map(|c| c.subject.clone())
725+
.collect::<Vec<_>>()
726+
.join("\n");
720727
assert!(commits.contains("first commit"));
721728
assert!(commits.contains("second commit"));
722729
assert!(commits.contains("third commit"));

rust/crates/runtime/src/session.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,8 +1441,12 @@ mod tests {
14411441
/// Called by external consumers (e.g. clawhip) to enumerate sessions for a CWD.
14421442
#[allow(dead_code)]
14431443
pub fn workspace_sessions_dir(cwd: &std::path::Path) -> Result<std::path::PathBuf, SessionError> {
1444-
let store = crate::session_control::SessionStore::from_cwd(cwd)
1445-
.map_err(|e| SessionError::Io(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())))?;
1444+
let store = crate::session_control::SessionStore::from_cwd(cwd).map_err(|e| {
1445+
SessionError::Io(std::io::Error::new(
1446+
std::io::ErrorKind::Other,
1447+
e.to_string(),
1448+
))
1449+
})?;
14461450
Ok(store.sessions_dir().to_path_buf())
14471451
}
14481452

@@ -1481,7 +1485,10 @@ mod workspace_sessions_dir_tests {
14811485

14821486
let dir_a = workspace_sessions_dir(&tmp_a).expect("dir a");
14831487
let dir_b = workspace_sessions_dir(&tmp_b).expect("dir b");
1484-
assert_ne!(dir_a, dir_b, "different CWDs must produce different session dirs");
1488+
assert_ne!(
1489+
dir_a, dir_b,
1490+
"different CWDs must produce different session dirs"
1491+
);
14851492

14861493
fs::remove_dir_all(&tmp_a).ok();
14871494
fs::remove_dir_all(&tmp_b).ok();

rust/crates/runtime/src/worker_boot.rs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,34 +1105,54 @@ mod tests {
11051105

11061106
#[test]
11071107
fn emit_state_file_writes_worker_status_on_transition() {
1108-
let cwd_path = std::env::temp_dir().join(format!("claw-state-test-{}", std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_nanos()));
1108+
let cwd_path = std::env::temp_dir().join(format!(
1109+
"claw-state-test-{}",
1110+
std::time::SystemTime::now()
1111+
.duration_since(std::time::UNIX_EPOCH)
1112+
.unwrap_or_default()
1113+
.as_nanos()
1114+
));
11091115
std::fs::create_dir_all(&cwd_path).expect("test dir should create");
11101116
let cwd = cwd_path.to_str().expect("test path should be utf8");
11111117
let registry = WorkerRegistry::new();
11121118
let worker = registry.create(cwd, &[], true);
11131119

11141120
// After create the worker is Spawning — state file should exist
11151121
let state_path = cwd_path.join(".claw").join("worker-state.json");
1116-
assert!(state_path.exists(), "state file should exist after worker creation");
1122+
assert!(
1123+
state_path.exists(),
1124+
"state file should exist after worker creation"
1125+
);
11171126

11181127
let raw = std::fs::read_to_string(&state_path).expect("state file should be readable");
1119-
let value: serde_json::Value = serde_json::from_str(&raw).expect("state file should be valid JSON");
1120-
assert_eq!(value["status"].as_str(), Some("spawning"), "initial status should be spawning");
1128+
let value: serde_json::Value =
1129+
serde_json::from_str(&raw).expect("state file should be valid JSON");
1130+
assert_eq!(
1131+
value["status"].as_str(),
1132+
Some("spawning"),
1133+
"initial status should be spawning"
1134+
);
11211135
assert_eq!(value["is_ready"].as_bool(), Some(false));
11221136

11231137
// Transition to ReadyForPrompt by observing trust-cleared text
11241138
registry
11251139
.observe(&worker.worker_id, "Ready for input\n>")
11261140
.expect("observe ready should succeed");
11271141

1128-
let raw = std::fs::read_to_string(&state_path).expect("state file should be readable after observe");
1129-
let value: serde_json::Value = serde_json::from_str(&raw).expect("state file should be valid JSON after observe");
1142+
let raw = std::fs::read_to_string(&state_path)
1143+
.expect("state file should be readable after observe");
1144+
let value: serde_json::Value =
1145+
serde_json::from_str(&raw).expect("state file should be valid JSON after observe");
11301146
assert_eq!(
11311147
value["status"].as_str(),
11321148
Some("ready_for_prompt"),
11331149
"status should be ready_for_prompt after observe"
11341150
);
1135-
assert_eq!(value["is_ready"].as_bool(), Some(true), "is_ready should be true when ReadyForPrompt");
1151+
assert_eq!(
1152+
value["is_ready"].as_bool(),
1153+
Some(true),
1154+
"is_ready should be true when ReadyForPrompt"
1155+
);
11361156
}
11371157

11381158
#[test]

0 commit comments

Comments
 (0)