fix: add --all to cargo fmt in script/test and autoformat codebase
cargo fmt without --all fails with "Failed to find targets" in workspace repos. This was blocking every story's gates. Also ran cargo fmt --all to fix all existing formatting issues. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+48
-67
@@ -161,10 +161,7 @@ pub(crate) async fn tick_once(
|
||||
}
|
||||
|
||||
let remaining = store.list().len();
|
||||
crate::slog!(
|
||||
"[timer] Tick: {} due, {remaining} remaining",
|
||||
due.len()
|
||||
);
|
||||
crate::slog!("[timer] Tick: {} due, {remaining} remaining", due.len());
|
||||
|
||||
for entry in due {
|
||||
crate::slog!("[timer] Timer fired for story {}", entry.story_id);
|
||||
@@ -287,9 +284,7 @@ pub fn spawn_rate_limit_auto_scheduler(
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(tokio::sync::broadcast::error::RecvError::Lagged(n)) => {
|
||||
crate::slog!(
|
||||
"[timer] Rate-limit auto-scheduler lagged, skipped {n} events"
|
||||
);
|
||||
crate::slog!("[timer] Rate-limit auto-scheduler lagged, skipped {n} events");
|
||||
}
|
||||
Err(tokio::sync::broadcast::error::RecvError::Closed) => {
|
||||
crate::slog!(
|
||||
@@ -398,44 +393,43 @@ pub async fn handle_timer_command(
|
||||
let story_id = match resolve_story_id(&story_number_or_id, project_root) {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
return format!(
|
||||
"No story with number or ID **{story_number_or_id}** found."
|
||||
);
|
||||
return format!("No story with number or ID **{story_number_or_id}** found.");
|
||||
}
|
||||
};
|
||||
|
||||
// The story must be in backlog or current. When the timer fires,
|
||||
// backlog stories are moved to current automatically.
|
||||
// Check CRDT state first, then fall back to filesystem.
|
||||
let in_valid_stage = if let Ok(Some(item)) = crate::pipeline_state::read_typed(&story_id) {
|
||||
use crate::pipeline_state::Stage;
|
||||
matches!(item.stage, Stage::Backlog | Stage::Coding)
|
||||
} else {
|
||||
let work_dir = project_root.join(".huskies").join("work");
|
||||
work_dir.join("1_backlog").join(format!("{story_id}.md")).exists()
|
||||
|| work_dir.join("2_current").join(format!("{story_id}.md")).exists()
|
||||
};
|
||||
let in_valid_stage =
|
||||
if let Ok(Some(item)) = crate::pipeline_state::read_typed(&story_id) {
|
||||
use crate::pipeline_state::Stage;
|
||||
matches!(item.stage, Stage::Backlog | Stage::Coding)
|
||||
} else {
|
||||
let work_dir = project_root.join(".huskies").join("work");
|
||||
work_dir
|
||||
.join("1_backlog")
|
||||
.join(format!("{story_id}.md"))
|
||||
.exists()
|
||||
|| work_dir
|
||||
.join("2_current")
|
||||
.join(format!("{story_id}.md"))
|
||||
.exists()
|
||||
};
|
||||
if !in_valid_stage {
|
||||
return format!(
|
||||
"Story **{story_id}** is not in backlog or current."
|
||||
);
|
||||
return format!("Story **{story_id}** is not in backlog or current.");
|
||||
}
|
||||
|
||||
let scheduled_at = match next_occurrence_of_hhmm(&hhmm, tz_str) {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
return format!(
|
||||
"Invalid time **{hhmm}**. Use `HH:MM` format (e.g. `14:30`)."
|
||||
);
|
||||
return format!("Invalid time **{hhmm}**. Use `HH:MM` format (e.g. `14:30`).");
|
||||
}
|
||||
};
|
||||
|
||||
match store.add(story_id.clone(), scheduled_at) {
|
||||
Ok(()) => {
|
||||
let (display_time, tz_label) = format_in_timezone(scheduled_at, tz_str);
|
||||
format!(
|
||||
"Timer set for **{story_id}** at **{display_time}** ({tz_label})."
|
||||
)
|
||||
format!("Timer set for **{story_id}** at **{display_time}** ({tz_label}).")
|
||||
}
|
||||
Err(e) => format!("Failed to save timer: {e}"),
|
||||
}
|
||||
@@ -448,11 +442,7 @@ pub async fn handle_timer_command(
|
||||
let mut lines = vec!["**Pending timers:**".to_string()];
|
||||
for t in &timers {
|
||||
let (display_time, _) = format_in_timezone(t.scheduled_at, tz_str);
|
||||
lines.push(format!(
|
||||
"- **{}** → {}",
|
||||
t.story_id,
|
||||
display_time
|
||||
));
|
||||
lines.push(format!("- **{}** → {}", t.story_id, display_time));
|
||||
}
|
||||
lines.join("\n")
|
||||
}
|
||||
@@ -465,13 +455,11 @@ pub async fn handle_timer_command(
|
||||
format!("No timer found for **{story_id}**.")
|
||||
}
|
||||
}
|
||||
TimerCommand::BadArgs => {
|
||||
"Usage:\n\
|
||||
TimerCommand::BadArgs => "Usage:\n\
|
||||
- `timer <story_id> <HH:MM>` — schedule deferred start\n\
|
||||
- `timer list` — show pending timers\n\
|
||||
- `timer cancel <story_id>` — remove a timer"
|
||||
.to_string()
|
||||
}
|
||||
.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,10 +517,7 @@ fn format_in_timezone(dt: DateTime<Utc>, timezone: Option<&str>) -> (String, Str
|
||||
match timezone.and_then(|s| s.parse::<Tz>().ok()) {
|
||||
Some(tz) => {
|
||||
let tz_time = dt.with_timezone(&tz);
|
||||
(
|
||||
tz_time.format("%Y-%m-%d %H:%M").to_string(),
|
||||
tz.to_string(),
|
||||
)
|
||||
(tz_time.format("%Y-%m-%d %H:%M").to_string(), tz.to_string())
|
||||
}
|
||||
None => {
|
||||
let local_time = dt.with_timezone(&Local);
|
||||
@@ -571,7 +556,12 @@ fn resolve_story_id(number_or_id: &str, project_root: &Path) -> Option<String> {
|
||||
// --- DB-first lookup ---
|
||||
for id in crate::db::all_content_ids() {
|
||||
let file_num = id.split('_').next().unwrap_or("");
|
||||
if file_num == number_or_id && crate::pipeline_state::read_typed(&id).ok().flatten().is_some() {
|
||||
if file_num == number_or_id
|
||||
&& crate::pipeline_state::read_typed(&id)
|
||||
.ok()
|
||||
.flatten()
|
||||
.is_some()
|
||||
{
|
||||
return Some(id);
|
||||
}
|
||||
}
|
||||
@@ -643,14 +633,20 @@ mod tests {
|
||||
#[test]
|
||||
fn next_occurrence_with_named_timezone_is_in_the_future() {
|
||||
let result = next_occurrence_of_hhmm("14:30", Some("Europe/London")).unwrap();
|
||||
assert!(result > Utc::now(), "next occurrence (Europe/London) must be in the future");
|
||||
assert!(
|
||||
result > Utc::now(),
|
||||
"next occurrence (Europe/London) must be in the future"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn next_occurrence_with_invalid_timezone_falls_back_to_local() {
|
||||
// An unrecognised timezone name falls back to chrono::Local (returns Some).
|
||||
let result = next_occurrence_of_hhmm("14:30", Some("Invalid/Zone"));
|
||||
assert!(result.is_some(), "invalid timezone should fall back to local and return Some");
|
||||
assert!(
|
||||
result.is_some(),
|
||||
"invalid timezone should fall back to local and return Some"
|
||||
);
|
||||
}
|
||||
|
||||
// ── extract_timer_command ───────────────────────────────────────────
|
||||
@@ -679,11 +675,7 @@ mod tests {
|
||||
#[test]
|
||||
fn timer_cancel_story_id() {
|
||||
assert_eq!(
|
||||
extract_timer_command(
|
||||
"Timmy timer cancel 421_story_foo",
|
||||
"Timmy",
|
||||
"@bot:home"
|
||||
),
|
||||
extract_timer_command("Timmy timer cancel 421_story_foo", "Timmy", "@bot:home"),
|
||||
Some(TimerCommand::Cancel {
|
||||
story_number_or_id: "421_story_foo".to_string()
|
||||
})
|
||||
@@ -701,11 +693,7 @@ mod tests {
|
||||
#[test]
|
||||
fn timer_schedule_with_story_id() {
|
||||
assert_eq!(
|
||||
extract_timer_command(
|
||||
"Timmy timer 421_story_foo 14:30",
|
||||
"Timmy",
|
||||
"@bot:home"
|
||||
),
|
||||
extract_timer_command("Timmy timer 421_story_foo 14:30", "Timmy", "@bot:home"),
|
||||
Some(TimerCommand::Schedule {
|
||||
story_number_or_id: "421_story_foo".to_string(),
|
||||
hhmm: "14:30".to_string(),
|
||||
@@ -727,11 +715,7 @@ mod tests {
|
||||
#[test]
|
||||
fn timer_schedule_missing_time_is_bad_args() {
|
||||
assert_eq!(
|
||||
extract_timer_command(
|
||||
"Timmy timer 421_story_foo",
|
||||
"Timmy",
|
||||
"@bot:home"
|
||||
),
|
||||
extract_timer_command("Timmy timer 421_story_foo", "Timmy", "@bot:home"),
|
||||
Some(TimerCommand::BadArgs)
|
||||
);
|
||||
}
|
||||
@@ -944,10 +928,7 @@ mod tests {
|
||||
dir.path(),
|
||||
)
|
||||
.await;
|
||||
assert!(
|
||||
result.contains("No timer found"),
|
||||
"unexpected: {result}"
|
||||
);
|
||||
assert!(result.contains("No timer found"), "unexpected: {result}");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -1014,10 +995,7 @@ mod tests {
|
||||
dir.path(),
|
||||
)
|
||||
.await;
|
||||
assert!(
|
||||
result.contains("Timer set for"),
|
||||
"unexpected: {result}"
|
||||
);
|
||||
assert!(result.contains("Timer set for"), "unexpected: {result}");
|
||||
assert_eq!(store.list().len(), 1);
|
||||
}
|
||||
|
||||
@@ -1111,7 +1089,10 @@ mod tests {
|
||||
"story should be in the content store after timer fires"
|
||||
);
|
||||
// Timer was consumed.
|
||||
assert!(store.list().is_empty(), "fired timer should be removed from store");
|
||||
assert!(
|
||||
store.list().is_empty(),
|
||||
"fired timer should be removed from store"
|
||||
);
|
||||
}
|
||||
|
||||
// ── AC4: tick_once integration test ─────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user