clippy: zero pedantic warnings across the tree

This commit is contained in:
damocles 2026-05-18 22:09:34 +02:00
parent 690cb5ab5b
commit f9f1346eae
20 changed files with 71 additions and 61 deletions

View file

@ -148,6 +148,7 @@ async fn main() -> Result<()> {
}
}
#[allow(clippy::too_many_arguments, clippy::similar_names)]
async fn serve(
socket: &Path,
interval: Duration,
@ -245,13 +246,13 @@ async fn serve(
s.record(&row);
}
// After turn completes, check if there are pending messages waiting.
// If so, immediately process them instead of blocking on recv().
// This ensures messages queued during the turn are processed ASAP.
// After turn completes, log whether messages arrived during
// the turn — the outer loop will iterate back to recv() on
// its own (the Empty-arm sleep only fires when recv
// actually returned Empty), so no explicit continue needed.
let pending = inbox_unread(socket).await;
if pending > 0 {
tracing::info!(%pending, "pending messages after turn; fetching next");
continue; // Loop back to recv() immediately instead of sleeping
}
}
Ok(AgentResponse::Empty) => {
@ -409,10 +410,11 @@ async fn fetch_agent_post_turn_counts(socket: &Path) -> (Option<u64>, Option<u64
(threads, reminders)
}
/// Assemble a TurnStatRow from the harness's per-turn state. Shared
/// Assemble a `TurnStatRow` from the harness's per-turn state. Shared
/// shape between the agent + manager bin loops (each lives in its own
/// crate root so this helper is duplicated; the savings of a shared
/// module aren't worth the cross-crate ceremony at this size).
#[allow(clippy::too_many_arguments)]
fn build_row(
started_at: i64,
ended_at: i64,

View file

@ -206,12 +206,12 @@ async fn serve(
);
s.record(&row);
}
// Check for messages that arrived during the turn and loop
// immediately if any are waiting — mirrors hive-ag3nt behaviour.
// Check for messages that arrived during the turn so we
// surface "draining" in the logs. The loop will already
// re-iterate from here — no explicit continue needed.
let pending = inbox_unread(socket).await;
if pending > 0 {
tracing::info!(%pending, "pending messages after turn; fetching next");
continue;
}
}
Ok(ManagerResponse::Empty) => {
@ -333,8 +333,9 @@ async fn fetch_manager_post_turn_counts(socket: &Path) -> (Option<u64>, Option<u
(threads, reminders)
}
/// Manager flavour of the agent's build_row helper. Duplicated rather
/// Manager flavour of the agent's `build_row` helper. Duplicated rather
/// than shared to keep each bin self-contained at this size.
#[allow(clippy::too_many_arguments)]
fn build_row(
started_at: i64,
ended_at: i64,

View file

@ -234,7 +234,7 @@ impl TokenUsage {
if v.get("type").and_then(|t| t.as_str()) != Some("result") {
return None;
}
Self::from_usage_obj(v.get("usage")?)
Some(Self::from_usage_obj(v.get("usage")?))
}
/// Parse usage from a per-inference `assistant` event's
@ -245,17 +245,17 @@ impl TokenUsage {
if v.get("type").and_then(|t| t.as_str()) != Some("assistant") {
return None;
}
Self::from_usage_obj(v.get("message")?.get("usage")?)
Some(Self::from_usage_obj(v.get("message")?.get("usage")?))
}
fn from_usage_obj(u: &serde_json::Value) -> Option<Self> {
fn from_usage_obj(u: &serde_json::Value) -> Self {
let field = |k: &str| u.get(k).and_then(serde_json::Value::as_u64).unwrap_or(0);
Some(Self {
Self {
input_tokens: field("input_tokens"),
output_tokens: field("output_tokens"),
cache_read_input_tokens: field("cache_read_input_tokens"),
cache_creation_input_tokens: field("cache_creation_input_tokens"),
})
}
}
}
@ -494,7 +494,7 @@ impl Bus {
});
}
/// Broadcast a status flip (online / needs_login_*). Called by
/// Broadcast a status flip (online / `needs_login_*`). Called by
/// the bin entry points + `turn::wait_for_login` + the
/// `post_login_*` handlers — every site that mutates the
/// `Arc<Mutex<LoginState>>` should also call this so the web UI

View file

@ -308,11 +308,13 @@ where
/// content failure and the model would burn a turn retrying it.
pub fn annotate_retries(mut s: String, retries: u32) -> String {
if retries > 0 {
use std::fmt::Write as _;
let suffix = if retries == 1 { "retry" } else { "retries" };
s.push_str(&format!(
let _ = write!(
s,
"\n\n(note: hive socket connect needed {retries} {suffix} — c0re likely \
restarted. Your request did succeed on the final attempt; no action needed.)"
));
);
}
s
}

View file

@ -27,9 +27,8 @@ const AUTO_UPDATE_PATH: &str = "/etc/hyperhive/claude-plugins-auto-update.json";
/// "already exists" message and exits non-zero on some versions).
/// Required before any `<plugin>@<marketplace>` install can resolve.
async fn add_marketplaces() {
let raw = match tokio::fs::read_to_string(MARKETPLACES_PATH).await {
Ok(s) => s,
Err(_) => return,
let Ok(raw) = tokio::fs::read_to_string(MARKETPLACES_PATH).await else {
return;
};
let sources: Vec<String> = match serde_json::from_str(&raw) {
Ok(v) => v,
@ -107,9 +106,8 @@ async fn update_marketplaces() {
/// journald. The manager itself passes `None` — there's nobody above
/// it to notify.
pub async fn install_configured(socket: &Path, notify_recipient: Option<&str>) {
let raw = match tokio::fs::read_to_string(PLUGINS_PATH).await {
Ok(s) => s,
Err(_) => return,
let Ok(raw) = tokio::fs::read_to_string(PLUGINS_PATH).await else {
return;
};
let specs: Vec<String> = match serde_json::from_str(&raw) {
Ok(v) => v,

View file

@ -222,7 +222,12 @@ pub async fn compact_session(files: &TurnFiles, bus: &Bus) -> Result<()> {
Ok(())
}
#[allow(clippy::too_many_lines)]
async fn run_claude(prompt: &str, files: &TurnFiles, bus: &Bus) -> Result<bool> {
// Keep the last STDERR_TAIL_LINES of stderr so a non-zero exit can
// include real context in the bail message (and downstream in the
// failure notification to the manager) instead of just "exit 1".
const STDERR_TAIL_LINES: usize = 20;
let model = bus.model();
let resume = !bus.take_skip_continue();
if !resume {
@ -311,10 +316,6 @@ async fn run_claude(prompt: &str, files: &TurnFiles, bus: &Bus) -> Result<bool>
}
}
});
// Keep the last STDERR_TAIL_LINES of stderr so a non-zero exit can
// include real context in the bail message (and downstream in the
// failure notification to the manager) instead of just "exit 1".
const STDERR_TAIL_LINES: usize = 20;
let stderr_tail: Arc<Mutex<VecDeque<String>>> =
Arc::new(Mutex::new(VecDeque::with_capacity(STDERR_TAIL_LINES)));
let tail_clone = stderr_tail.clone();

View file

@ -1,8 +1,8 @@
//! Per-turn analytics sink. One sqlite row per claude turn captures:
//! identity (model, wake_from, result_kind), timing (started_at,
//! ended_at, duration_ms), cost (token counts), behaviour (tool-call
//! identity (`model`, `wake_from`, `result_kind`), timing (`started_at`,
//! `ended_at`, `duration_ms`), cost (token counts), behaviour (tool-call
//! count + per-tool breakdown), and post-turn snapshot metrics
//! (open_threads_count, open_reminders_count).
//! (`open_threads_count`, `open_reminders_count`).
//!
//! Lives next to `hyperhive-events.sqlite` in the agent's state dir
//! so the host-side state vacuum sweep can reach both. Schema is
@ -65,7 +65,7 @@ const MIGRATIONS: &[&str] = &[
/// One row to be inserted. `Option`-wrapped fields default to NULL
/// when the harness couldn't gather them (e.g. socket roundtrip for
/// open_threads failed) so a partial row beats no row.
/// `open_threads` failed) so a partial row beats no row.
#[derive(Debug, Clone)]
pub struct TurnStatRow {
pub started_at: i64,

View file

@ -527,11 +527,8 @@ async fn post_compact(State(state): State<AppState>) -> Response {
let lock = state.turn_lock.clone();
// Reject immediately if a normal turn is in flight — concurrent access
// to the claude session is unsafe and produces garbled output.
let guard = match lock.try_lock_owned() {
Ok(g) => g,
Err(_) => {
return error_response("turn in flight — wait for it to finish before compacting");
}
let Ok(guard) = lock.try_lock_owned() else {
return error_response("turn in flight — wait for it to finish before compacting");
};
let bus = state.bus.clone();
let files = state.files.clone();