Skip to content

Commit 7224381

Browse files
committed
Add mixed ID style detection to doctor
Detects when tickets have a mix of sequential (all digits) and random (alphanumeric) ID suffixes, which can happen when switching id_mode. Warns users about the inconsistency but doesn't block functionality.
1 parent 05b20f7 commit 7224381

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
+++
2+
id = "peas-73fw8"
3+
title = "Detect mixed ID styles in doctor"
4+
type = "feature"
5+
status = "completed"
6+
priority = "normal"
7+
created = "2026-02-02T23:12:57.060623500Z"
8+
updated = "2026-02-02T23:13:54.922261900Z"
9+
+++
10+
11+
Add a check to peas doctor that detects when tickets have mixed ID styles (random vs sequential), which can happen when switching id_mode. Warn users about the inconsistency but don't block - it's functional, just messy.

src/cli/handlers/doctor.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ pub fn handle_doctor(fix: bool) -> Result<()> {
5555
// Check 4: Ticket integrity
5656
check_ticket_integrity(&cwd, &mut results)?;
5757

58-
// Check 5: Sequential ID counter (if applicable)
58+
// Check 5: Mixed ID styles
59+
check_mixed_id_styles(&cwd, &mut results)?;
60+
61+
// Check 6: Sequential ID counter (if applicable)
5962
check_sequential_counter(&cwd, &mut results, fix)?;
6063

6164
// Summary
@@ -346,6 +349,60 @@ fn check_ticket_integrity(cwd: &Path, results: &mut DiagnosticResults) -> Result
346349
Ok(())
347350
}
348351

352+
fn check_mixed_id_styles(cwd: &Path, results: &mut DiagnosticResults) -> Result<()> {
353+
let data_dir = cwd.join(DATA_DIR);
354+
if !data_dir.exists() {
355+
return Ok(());
356+
}
357+
358+
let mut sequential_ids: Vec<String> = Vec::new();
359+
let mut random_ids: Vec<String> = Vec::new();
360+
361+
for entry in std::fs::read_dir(&data_dir)? {
362+
let entry = entry?;
363+
let path = entry.path();
364+
365+
if path.is_file() && path.extension().map(|e| e == "md").unwrap_or(false) {
366+
let content = std::fs::read_to_string(&path)?;
367+
368+
if let Ok(pea) = crate::storage::parse_markdown(&content) {
369+
// Extract the suffix (part after the last hyphen in the prefix)
370+
// e.g., "peas-00042" -> "00042", "peas-a1b2c" -> "a1b2c"
371+
if let Some(suffix) = pea.id.rsplit('-').next() {
372+
// Sequential IDs are all digits (possibly with leading zeros)
373+
if suffix.chars().all(|c| c.is_ascii_digit()) {
374+
sequential_ids.push(pea.id.clone());
375+
} else {
376+
random_ids.push(pea.id.clone());
377+
}
378+
}
379+
}
380+
}
381+
}
382+
383+
// Only report if we have both styles
384+
if !sequential_ids.is_empty() && !random_ids.is_empty() {
385+
println!("{}", "ID Style Consistency".bold());
386+
results.warn("Mixed ID styles detected");
387+
println!(
388+
" Sequential IDs: {} (e.g., {})",
389+
sequential_ids.len(),
390+
sequential_ids.first().unwrap()
391+
);
392+
println!(
393+
" Random IDs: {} (e.g., {})",
394+
random_ids.len(),
395+
random_ids.first().unwrap()
396+
);
397+
results.suggestion(
398+
"This can happen when switching id_mode - it's functional but inconsistent",
399+
);
400+
println!();
401+
}
402+
403+
Ok(())
404+
}
405+
349406
fn check_sequential_counter(cwd: &Path, results: &mut DiagnosticResults, fix: bool) -> Result<()> {
350407
let data_dir = cwd.join(DATA_DIR);
351408
let counter_path = data_dir.join(".id");

0 commit comments

Comments
 (0)