git-worktree-manager 0.0.39

CLI tool integrating git worktree with AI coding assistants
Documentation
use git_worktree_manager::operations::busy::{BusyInfo, BusySource, BusyTier};
use git_worktree_manager::operations::busy_messages::render_refusal;
use std::path::PathBuf;

fn hard_claude(secs: u64) -> BusyInfo {
    BusyInfo {
        pid: 0,
        cmd: "claude (session abc123)".into(),
        cwd: PathBuf::from("/tmp/wt"),
        source: BusySource::ClaudeSession,
        tier: BusyTier::Hard,
        tty: None,
        started_secs_ago: Some(secs),
    }
}

fn soft_proc(pid: u32, cmd: &str, tty: bool, started: u64) -> BusyInfo {
    BusyInfo {
        pid,
        cmd: cmd.into(),
        cwd: PathBuf::from("/tmp/wt"),
        source: BusySource::ProcessScan,
        tier: BusyTier::Soft,
        tty: Some(tty),
        started_secs_ago: Some(started),
    }
}

#[test]
fn soft_only_uses_warning_tone() {
    let s = render_refusal("feature-x", &[], &[soft_proc(123, "zsh", true, 60)]);
    assert!(
        s.contains("may be in use"),
        "soft-only must use 'may be in use' wording"
    );
    assert!(s.contains("Re-run with --force"));
    assert!(!s.contains("Cannot delete"));
}

#[test]
fn hard_only_uses_strong_refusal() {
    let s = render_refusal("feature-x", &[hard_claude(120)], &[]);
    assert!(s.contains("Cannot delete worktree 'feature-x'"));
    assert!(s.contains("Active Claude session"));
    assert!(s.contains("Use --force"));
}

#[test]
fn both_tiers_lead_with_hard_then_show_soft() {
    let s = render_refusal(
        "feature-x",
        &[hard_claude(60)],
        &[soft_proc(7, "cargo build", false, 30)],
    );
    let hard_pos = s.find("Active Claude session").unwrap();
    let soft_pos = s.find("Additional processes").unwrap();
    assert!(hard_pos < soft_pos, "Hard section must precede Soft");
}