clippy: fix lints that crane's cargoClippy properly enforces (#538)
The naersk → crane swap in the parent commit flips clippy from silently passing to actually failing on `-D warnings` (naersk's `mode = "clippy"` mangled the `--` separator so the deny never took effect). This commit clears the surfaced lints so the workspace builds clean under the new enforcement — every fix is mechanical and preserves behaviour. Tests still pass (160 across the workspace). Auto-fixes via `cargo clippy --fix`: - `doc_markdown` (19 sites): bare identifiers in doc comments wrapped in backticks - `format_in_format_args`, `explicit_into_iter_loop`, `redundant_closure_for_method_calls`, `useless_conversion`, and a few more — mechanical rewrites of the kind cargo can apply safely. Hand-fixed: - `match_same_arms` (forge_notify::is_atx_heading): two arms returning `true` collapsed into a single `matches!` pattern. - `cast_sign_loss` + `format_push_string` (mcp.rs status formatter): guarded `i64 → u64` through `u64::try_from(…).unwrap_or(0)` (status timestamps are always positive in practice; clamp the skew edge to 0) and swapped `out.push_str(&format!(…))` for `write!` into the buffer with an infallible-writer `let _ =`. - `doc_lazy_continuation` in turn.rs + manager_server.rs + sh4re/lib.rs: doc paragraphs that the markdown parser was treating as list-item continuations got either a separating blank line or a `/`-for-`+` word swap so the parser stops seeing a list. - `unused_async` (manager_server::handle_request_schedule_prompt): function has no `.await`; dropped the `async` and its `.await` call site. - `needless_pass_by_value` (scheduled_prompts::submit): take `&NewSchedule` instead of moving the struct in; updated two prod callers and eight test sites to pass references. - `type_complexity` (approvals::mark_cancelled): hoisted the 7-tuple SELECT row shape into a `type CancelLookupRow = (…);` alias. Allow-with-reason for intentional patterns: - `option_option` (6 sites across dashboard / scheduled_prompts / manager_server): `Option<Option<T>>` carries three-state PATCH semantics (missing key = leave alone, `Some(None)` = clear, `Some(Some(v))` = set). Collapsing to `Option<T>` loses the "clear" state. - `dead_code` (rebuild_queue::QueueKind::Destroy / QueueSource::CrashRecover; topology::parent_of / default_seed): wire-shape variants + API surfaces kept for the upcoming features (#361 follow-ups, future `Destroy` queue routing, crash-recovery path). Allowed at the variant / function level with the rationale in `reason = "…"`. - `too_many_lines` on three specific call-sites: a 117-line exhaustive-variant test (dashboard_events::kind_tag_matches_…), the meta-flake string template renderer (meta::render_flake_with_lookup), and the notification poll loop (forge_notify::poll_once) — splitting any of them would just hide the contiguous shape they exist to keep visible. `nix flake check` formatting target is still broken on main itself (pre-existing nixfmt drift across ~28 files unrelated to this PR); left alone here so the scope stays "crane port + lints the port exposed" and the operator's review doesn't have to triage drive-by nixfmt churn.
This commit is contained in:
parent
4b6c733afb
commit
9ed58ab96d
17 changed files with 643 additions and 463 deletions
|
|
@ -47,7 +47,7 @@ pub enum SocketReply {
|
|||
Recent(Vec<hive_sh4re::InboxRow>),
|
||||
Logs(String),
|
||||
/// `list_schedules` result — used by the manager surface only;
|
||||
/// AgentResponse has no equivalent variant.
|
||||
/// `AgentResponse` has no equivalent variant.
|
||||
Schedules(Vec<hive_sh4re::WireSchedule>),
|
||||
LooseEnds(Vec<hive_sh4re::LooseEnd>),
|
||||
PendingRemindersCount(u64),
|
||||
|
|
@ -185,8 +185,7 @@ pub fn format_recv(resp: Result<SocketReply, anyhow::Error>) -> String {
|
|||
/// resurfaced by `RequeueInflight` on this session's boot. Same
|
||||
/// string surfaces in the wake prompt (see the bin loops) and the
|
||||
/// in-turn `recv` tool result so claude sees the warning either way.
|
||||
pub const REDELIVERY_HINT: &str =
|
||||
"[redelivered after harness restart — may already be handled]\n";
|
||||
pub const REDELIVERY_HINT: &str = "[redelivered after harness restart — may already be handled]\n";
|
||||
|
||||
/// Format helper for `get_loose_ends`: renders a short bulleted list
|
||||
/// of pending approvals + questions + reminders. Empty list collapses
|
||||
|
|
@ -307,17 +306,32 @@ pub fn format_agent_meta(resp: Result<SocketReply, anyhow::Error>) -> String {
|
|||
match status_text {
|
||||
None => out.push_str("\nstatus: <none>"),
|
||||
Some(s) => {
|
||||
use std::fmt::Write as _;
|
||||
let age = status_set_at.and_then(|ts| {
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.ok()?
|
||||
.as_secs();
|
||||
let secs = now.saturating_sub(ts as u64);
|
||||
// `ts` is a unix epoch second the agent itself
|
||||
// sourced from `SystemTime` — always positive
|
||||
// in normal operation. Clamp the negative
|
||||
// (clock-skew) edge to 0 before the unsigned
|
||||
// cast so the cast loses no real precision.
|
||||
let ts_secs = u64::try_from(ts).unwrap_or(0);
|
||||
let secs = now.saturating_sub(ts_secs);
|
||||
Some(format_age_secs(secs))
|
||||
});
|
||||
// `write!` into the buffer instead of `push_str(&format!(…))` —
|
||||
// avoids the intermediate allocation clippy::format_push_string
|
||||
// flags. The infallible `String` writer makes this safe to
|
||||
// `let _ =`-ignore.
|
||||
match age {
|
||||
Some(a) => out.push_str(&format!("\nstatus: {s} (set {a} ago)")),
|
||||
None => out.push_str(&format!("\nstatus: {s}")),
|
||||
Some(a) => {
|
||||
let _ = write!(out, "\nstatus: {s} (set {a} ago)");
|
||||
}
|
||||
None => {
|
||||
let _ = write!(out, "\nstatus: {s}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -626,9 +640,13 @@ impl AgentServer {
|
|||
)]
|
||||
async fn set_status(&self, Parameters(args): Parameters<SetStatusArgs>) -> String {
|
||||
run_tool_envelope("set_status", args.text.clone(), async move {
|
||||
let (resp, retries) =
|
||||
self.dispatch(hive_sh4re::AgentRequest::SetStatus { text: args.text }).await;
|
||||
annotate_retries(format_ack(resp, "set_status", "status updated".to_owned()), retries)
|
||||
let (resp, retries) = self
|
||||
.dispatch(hive_sh4re::AgentRequest::SetStatus { text: args.text })
|
||||
.await;
|
||||
annotate_retries(
|
||||
format_ack(resp, "set_status", "status updated".to_owned()),
|
||||
retries,
|
||||
)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
|
@ -644,10 +662,7 @@ impl AgentServer {
|
|||
where the system-prompt label could be stale. Status reads `<none>` when the \
|
||||
target has never called `set_status` or has cleared it."
|
||||
)]
|
||||
async fn get_agent_meta(
|
||||
&self,
|
||||
Parameters(args): Parameters<GetAgentMetaArgs>,
|
||||
) -> String {
|
||||
async fn get_agent_meta(&self, Parameters(args): Parameters<GetAgentMetaArgs>) -> String {
|
||||
let log = args.name.clone().unwrap_or_else(|| "<self>".to_owned());
|
||||
run_tool_envelope("get_agent_meta", log, async move {
|
||||
let (resp, retries) = self
|
||||
|
|
@ -679,7 +694,11 @@ impl AgentServer {
|
|||
.dispatch(hive_sh4re::AgentRequest::CancelLooseEnd { kind, id })
|
||||
.await;
|
||||
annotate_retries(
|
||||
format_ack(resp, "cancel_loose_end", format!("cancelled {kind_label} {id}")),
|
||||
format_ack(
|
||||
resp,
|
||||
"cancel_loose_end",
|
||||
format!("cancelled {kind_label} {id}"),
|
||||
),
|
||||
retries,
|
||||
)
|
||||
})
|
||||
|
|
@ -721,7 +740,10 @@ impl AgentServer {
|
|||
file_path: args.file_path,
|
||||
})
|
||||
.await;
|
||||
annotate_retries(format_ack(resp, "remind", "reminder scheduled".to_string()), retries)
|
||||
annotate_retries(
|
||||
format_ack(resp, "remind", "reminder scheduled".to_string()),
|
||||
retries,
|
||||
)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
|
@ -949,7 +971,7 @@ pub struct RequestSchedulePromptArgs {
|
|||
/// `None` / absent = one-shot. `Some(n > 0)` = recurring every
|
||||
/// `n` seconds. The worker clamps catch-up so a long downtime
|
||||
/// fires ONCE on resume (skipped-cycle count surfaces in the
|
||||
/// per-target last_result), not N delayed pulses in a row.
|
||||
/// per-target `last_result`), not N delayed pulses in a row.
|
||||
#[serde(default)]
|
||||
pub interval_seconds: Option<u64>,
|
||||
/// Optional description shown on the dashboard approval card +
|
||||
|
|
@ -1301,10 +1323,7 @@ impl ManagerServer {
|
|||
Authorization mirrors `cancel_schedule`: you can fire your own schedules + any \
|
||||
owned by a sub-agent in your subtree per topology.json."
|
||||
)]
|
||||
async fn fire_schedule_now(
|
||||
&self,
|
||||
Parameters(args): Parameters<FireScheduleNowArgs>,
|
||||
) -> String {
|
||||
async fn fire_schedule_now(&self, Parameters(args): Parameters<FireScheduleNowArgs>) -> String {
|
||||
let log = format!("{args:?}");
|
||||
run_tool_envelope("fire_schedule_now", log, async move {
|
||||
let id = args.id;
|
||||
|
|
@ -1337,7 +1356,10 @@ impl ManagerServer {
|
|||
targets: args.targets,
|
||||
})
|
||||
.await;
|
||||
annotate_retries(format_ack(resp, "cancel_schedule", format!("cancelled #{id}")), retries)
|
||||
annotate_retries(
|
||||
format_ack(resp, "cancel_schedule", format!("cancelled #{id}")),
|
||||
retries,
|
||||
)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
|
@ -1394,7 +1416,9 @@ impl ManagerServer {
|
|||
)]
|
||||
async fn list_schedules(&self) -> String {
|
||||
run_tool_envelope("list_schedules", String::new(), async move {
|
||||
let (resp, retries) = self.dispatch(hive_sh4re::ManagerRequest::ListSchedules).await;
|
||||
let (resp, retries) = self
|
||||
.dispatch(hive_sh4re::ManagerRequest::ListSchedules)
|
||||
.await;
|
||||
let body = match resp {
|
||||
Ok(SocketReply::Schedules(schedules)) => serde_json::to_string(&schedules)
|
||||
.unwrap_or_else(|e| format!("list_schedules: serialise: {e:#}")),
|
||||
|
|
@ -1541,7 +1565,10 @@ impl ManagerServer {
|
|||
file_path: args.file_path,
|
||||
})
|
||||
.await;
|
||||
annotate_retries(format_ack(resp, "remind", "reminder scheduled".to_string()), retries)
|
||||
annotate_retries(
|
||||
format_ack(resp, "remind", "reminder scheduled".to_string()),
|
||||
retries,
|
||||
)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
|
@ -1573,9 +1600,13 @@ impl ManagerServer {
|
|||
)]
|
||||
async fn set_status(&self, Parameters(args): Parameters<SetStatusArgs>) -> String {
|
||||
run_tool_envelope("set_status", args.text.clone(), async move {
|
||||
let (resp, retries) =
|
||||
self.dispatch(hive_sh4re::ManagerRequest::SetStatus { text: args.text }).await;
|
||||
annotate_retries(format_ack(resp, "set_status", "status updated".to_owned()), retries)
|
||||
let (resp, retries) = self
|
||||
.dispatch(hive_sh4re::ManagerRequest::SetStatus { text: args.text })
|
||||
.await;
|
||||
annotate_retries(
|
||||
format_ack(resp, "set_status", "status updated".to_owned()),
|
||||
retries,
|
||||
)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
|
@ -1590,10 +1621,7 @@ impl ManagerServer {
|
|||
drift across renames. Status reads `<none>` when the target has never called \
|
||||
`set_status` or has cleared it."
|
||||
)]
|
||||
async fn get_agent_meta(
|
||||
&self,
|
||||
Parameters(args): Parameters<GetAgentMetaArgs>,
|
||||
) -> String {
|
||||
async fn get_agent_meta(&self, Parameters(args): Parameters<GetAgentMetaArgs>) -> String {
|
||||
let log = args.name.clone().unwrap_or_else(|| "<self>".to_owned());
|
||||
run_tool_envelope("get_agent_meta", log, async move {
|
||||
let (resp, retries) = self
|
||||
|
|
@ -1628,7 +1656,11 @@ impl ManagerServer {
|
|||
.dispatch(hive_sh4re::ManagerRequest::CancelLooseEnd { kind, id })
|
||||
.await;
|
||||
annotate_retries(
|
||||
format_ack(resp, "cancel_loose_end", format!("cancelled {kind_label} {id}")),
|
||||
format_ack(
|
||||
resp,
|
||||
"cancel_loose_end",
|
||||
format!("cancelled {kind_label} {id}"),
|
||||
),
|
||||
retries,
|
||||
)
|
||||
})
|
||||
|
|
@ -1800,10 +1832,7 @@ pub fn allowed_tools_arg(flavor: Flavor) -> String {
|
|||
if patterns.is_empty() {
|
||||
vec!["Bash".to_owned()]
|
||||
} else {
|
||||
patterns
|
||||
.into_iter()
|
||||
.map(|p| format!("Bash({p})"))
|
||||
.collect()
|
||||
patterns.into_iter().map(|p| format!("Bash({p})")).collect()
|
||||
}
|
||||
} else {
|
||||
vec![(*s).to_owned()]
|
||||
|
|
|
|||
Loading…
Reference in a new issue