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
|
|
@ -164,6 +164,12 @@ pub struct NewSchedule {
|
|||
/// "this target is active again"; prior history was already visible
|
||||
/// at cancel time).
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[allow(
|
||||
clippy::option_option,
|
||||
reason = "double-Option carries three-state PATCH semantics: outer None = \
|
||||
leave alone, Some(None) = clear, Some(Some(v)) = set. \
|
||||
collapsing to a single Option would lose the 'clear' state"
|
||||
)]
|
||||
pub struct UpdateSchedule {
|
||||
pub body: Option<String>,
|
||||
pub description: Option<Option<String>>,
|
||||
|
|
@ -200,7 +206,7 @@ impl ScheduledPrompts {
|
|||
/// Insert a new schedule. Returns the new id. Empty `targets` is
|
||||
/// rejected — a schedule with no recipients would silently
|
||||
/// never fan out, masking caller bugs.
|
||||
pub fn submit(&self, new: NewSchedule) -> Result<i64> {
|
||||
pub fn submit(&self, new: &NewSchedule) -> Result<i64> {
|
||||
if new.targets.is_empty() {
|
||||
bail!("schedule must have at least one target");
|
||||
}
|
||||
|
|
@ -212,13 +218,13 @@ impl ScheduledPrompts {
|
|||
created_at_unix, source, description)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
||||
params![
|
||||
new.owner,
|
||||
new.body,
|
||||
&new.owner,
|
||||
&new.body,
|
||||
new.interval_seconds.map(i64::try_from).and_then(Result::ok),
|
||||
new.first_fire_at_unix,
|
||||
now_unix(),
|
||||
new.source.to_db_string(),
|
||||
new.description,
|
||||
&new.description,
|
||||
],
|
||||
)?;
|
||||
let id = tx.last_insert_rowid();
|
||||
|
|
@ -255,7 +261,7 @@ impl ScheduledPrompts {
|
|||
|
||||
/// Every active (non-globally-cancelled) schedule in insert
|
||||
/// order. Used by the dashboard list view + the cancel-auth
|
||||
/// check (the latter only needs the header but list() is the
|
||||
/// check (the latter only needs the header but `list()` is the
|
||||
/// shared hot path).
|
||||
pub fn list(&self) -> Result<Vec<Schedule>> {
|
||||
let conn = self.conn.lock().unwrap();
|
||||
|
|
@ -322,7 +328,7 @@ impl ScheduledPrompts {
|
|||
/// Advance a recurring schedule's `next_fire_at` to the smallest
|
||||
/// multiple-of-interval > `from`. Returns the count of skipped
|
||||
/// cycles (≥ 0); the worker stamps that into the per-row
|
||||
/// last_result so operators see "caught up from N missed".
|
||||
/// `last_result` so operators see "caught up from N missed".
|
||||
///
|
||||
/// For one-shots (`interval_seconds IS NULL`) this is a no-op
|
||||
/// at the SQL level; callers should `delete` them after fan-out
|
||||
|
|
@ -488,10 +494,7 @@ impl ScheduledPrompts {
|
|||
/// id.
|
||||
pub fn delete(&self, id: i64) -> Result<()> {
|
||||
let conn = self.conn.lock().unwrap();
|
||||
conn.execute(
|
||||
"DELETE FROM scheduled_prompts WHERE id = ?1",
|
||||
params![id],
|
||||
)?;
|
||||
conn.execute("DELETE FROM scheduled_prompts WHERE id = ?1", params![id])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -630,7 +633,7 @@ mod tests {
|
|||
}
|
||||
|
||||
fn submit_one_shot(db: &ScheduledPrompts, fire_at: i64, targets: &[&str]) -> i64 {
|
||||
db.submit(NewSchedule {
|
||||
db.submit(&NewSchedule {
|
||||
owner: "operator".into(),
|
||||
targets: targets.iter().map(|t| (*t).to_owned()).collect(),
|
||||
body: "wake".into(),
|
||||
|
|
@ -658,7 +661,7 @@ mod tests {
|
|||
fn submit_rejects_empty_targets() {
|
||||
let (_dir, db) = open();
|
||||
let err = db
|
||||
.submit(NewSchedule {
|
||||
.submit(&NewSchedule {
|
||||
owner: "operator".into(),
|
||||
targets: Vec::new(),
|
||||
body: "wake".into(),
|
||||
|
|
@ -688,7 +691,7 @@ mod tests {
|
|||
let (_dir, db) = open();
|
||||
// Recurring every 60s, last fire at t=100.
|
||||
let id = db
|
||||
.submit(NewSchedule {
|
||||
.submit(&NewSchedule {
|
||||
owner: "operator".into(),
|
||||
targets: vec!["alice".into()],
|
||||
body: "wake".into(),
|
||||
|
|
@ -710,7 +713,7 @@ mod tests {
|
|||
fn rearm_advances_one_step_when_caught_up() {
|
||||
let (_dir, db) = open();
|
||||
let id = db
|
||||
.submit(NewSchedule {
|
||||
.submit(&NewSchedule {
|
||||
owner: "operator".into(),
|
||||
targets: vec!["alice".into()],
|
||||
body: "wake".into(),
|
||||
|
|
@ -742,7 +745,8 @@ mod tests {
|
|||
fn cancel_targets_auto_cancels_parent_when_last_drops() {
|
||||
let (_dir, db) = open();
|
||||
let id = submit_one_shot(&db, 100, &["alice", "bob"]);
|
||||
db.cancel_targets(id, &["alice".to_owned()]).expect("cancel");
|
||||
db.cancel_targets(id, &["alice".to_owned()])
|
||||
.expect("cancel");
|
||||
let s = db.get(id).expect("get").expect("present");
|
||||
// Parent still active (bob remains).
|
||||
assert!(s.cancelled_at_unix.is_none());
|
||||
|
|
@ -775,7 +779,8 @@ mod tests {
|
|||
fn record_target_result_skips_cancelled_targets() {
|
||||
let (_dir, db) = open();
|
||||
let id = submit_one_shot(&db, 100, &["alice", "bob"]);
|
||||
db.cancel_targets(id, &["alice".to_owned()]).expect("cancel");
|
||||
db.cancel_targets(id, &["alice".to_owned()])
|
||||
.expect("cancel");
|
||||
db.record_target_result(id, "alice", 200, "ok")
|
||||
.expect("record alice");
|
||||
db.record_target_result(id, "bob", 200, "ok")
|
||||
|
|
@ -794,7 +799,7 @@ mod tests {
|
|||
fn update_partial_only_touches_set_fields() {
|
||||
let (_dir, db) = open();
|
||||
let id = db
|
||||
.submit(NewSchedule {
|
||||
.submit(&NewSchedule {
|
||||
owner: "operator".into(),
|
||||
targets: vec!["alice".into()],
|
||||
body: "old body".into(),
|
||||
|
|
@ -824,7 +829,7 @@ mod tests {
|
|||
fn update_interval_toggle_recurring_to_one_shot() {
|
||||
let (_dir, db) = open();
|
||||
let id = db
|
||||
.submit(NewSchedule {
|
||||
.submit(&NewSchedule {
|
||||
owner: "operator".into(),
|
||||
targets: vec!["alice".into()],
|
||||
body: "x".into(),
|
||||
|
|
@ -899,7 +904,7 @@ mod tests {
|
|||
fn update_clears_description() {
|
||||
let (_dir, db) = open();
|
||||
let id = db
|
||||
.submit(NewSchedule {
|
||||
.submit(&NewSchedule {
|
||||
owner: "operator".into(),
|
||||
targets: vec!["alice".into()],
|
||||
body: "x".into(),
|
||||
|
|
@ -982,7 +987,8 @@ mod tests {
|
|||
let (_dir, db) = open();
|
||||
let id = submit_one_shot(&db, 100, &["alice", "bob"]);
|
||||
// Record some history on alice, then cancel her.
|
||||
db.record_target_result(id, "alice", 50, "ok").expect("record");
|
||||
db.record_target_result(id, "alice", 50, "ok")
|
||||
.expect("record");
|
||||
db.update(
|
||||
id,
|
||||
UpdateSchedule {
|
||||
|
|
@ -1034,7 +1040,7 @@ mod tests {
|
|||
fn approval_source_round_trips() {
|
||||
let (_dir, db) = open();
|
||||
let id = db
|
||||
.submit(NewSchedule {
|
||||
.submit(&NewSchedule {
|
||||
owner: "manager".into(),
|
||||
targets: vec!["alice".into()],
|
||||
body: "wake".into(),
|
||||
|
|
|
|||
Loading…
Reference in a new issue