clt-rs 0.9.3

File-backed task manager with a TUI Kanban board and multi-project Codex agent registry
use super::*;
use crate::{
    agent::{AgentSessionControlState, NewGitFinalization, recovery},
    task::init_tasks,
    test_support::temp_root,
    worker::tests::reserve_test_worker,
};
use std::fs;

#[test]
fn git_defaults_can_change_without_mutating_active_owners_or_pending_proof() {
    for owner in [
        "dispatching",
        "running",
        "finalizing",
        "interactive",
        "working",
        "tracking",
        "commit_pending",
        "push_pending",
        "launch",
    ] {
        let root = temp_root("git-default-active-owner");
        let project_root = root.join("project");
        init_tasks(&project_root, false).unwrap();
        let state_dir = root.join("state");
        let store = TursoAgentStore::open_blocking(&state_dir).unwrap();
        store
            .register_project_blocking(&project_root, "project")
            .unwrap();
        let project = store.list_projects_blocking().unwrap().remove(0);
        store
            .set_project_git_mode_blocking(project.id, AgentGitMode::Commit)
            .unwrap();
        match owner {
            "dispatching" | "running" | "finalizing" | "interactive" | "launch" => {
                assert!(
                    store
                        .try_acquire_lease_blocking(project.id, "owner", "100", "9999999999")
                        .unwrap()
                );
                if owner == "interactive" {
                    assert!(
                        store
                            .reserve_idle_session_interactive_blocking(
                                project.id, "session", "owner", None
                            )
                            .unwrap()
                    );
                    store
                        .set_session_control_state_blocking(
                            project.id,
                            "session",
                            AgentSessionControlState::Interactive,
                        )
                        .unwrap();
                } else {
                    assert!(reserve_test_worker(
                        &store, project.id, "worker", "owner", "101", 1
                    ));
                    store
                        .blocking
                        .block_on_persist(async {
                            let conn = store.repositories.projects_models.connect().await?;
                            conn.execute(
                                "UPDATE agent_workers SET state = ?1 WHERE project_id = ?2",
                                params![
                                    if owner == "launch" { "running" } else { owner },
                                    project.id
                                ],
                            )
                            .await?;
                            Ok(())
                        })
                        .unwrap();
                }
                if owner == "launch" {
                    store
                        .record_git_launch_state_blocking(
                            project.id,
                            "worker",
                            AgentGitMode::Commit,
                            &crate::managed_git::AgentGitStartState {
                                starting_head: "frozen-head".into(),
                                branch_ref: Some("refs/heads/main".into()),
                                upstream_ref: None,
                                worktree_baseline: "{}".into(),
                            },
                            "100",
                        )
                        .unwrap();
                }
            }
            _ => {
                assert!(
                    store
                        .create_git_finalization_blocking(NewGitFinalization {
                            project_id: project.id,
                            codex_session_id: "session",
                            git_mode: AgentGitMode::Commit,
                            starting_head: Some("frozen-head"),
                            branch_ref: Some("refs/heads/main"),
                            upstream_ref: None,
                            worktree_baseline: "{}",
                            task_identity: Some("task"),
                            owner_run_token: None,
                            created_at: "100",
                        })
                        .unwrap()
                );
                store
                    .blocking
                    .block_on_persist(async {
                        let conn = store.repositories.projects_models.connect().await?;
                        conn.execute(
                            "UPDATE git_finalizations SET state = ?1 WHERE project_id = ?2",
                            params![owner, project.id],
                        )
                        .await?;
                        Ok(())
                    })
                    .unwrap();
            }
        }
        let before = recovery::read_snapshot(&state_dir).unwrap().unwrap();
        for by_path in [false, true] {
            for mode in [
                AgentGitMode::Off,
                AgentGitMode::Commit,
                AgentGitMode::CommitAndPush,
            ] {
                let changed = if by_path {
                    store.set_project_git_mode_for_path_blocking(&project_root, mode)
                } else {
                    store.set_project_git_mode_blocking(project.id, mode)
                }
                .unwrap();
                assert!(changed, "{owner}");
                assert_eq!(store.list_projects_blocking().unwrap()[0].git_mode, mode);
                let after = recovery::read_snapshot(&state_dir).unwrap().unwrap();
                for table in [
                    "leases",
                    "agent_workers",
                    "session_controls",
                    "session_git_modes",
                    "agent_git_launch_states",
                    "git_finalizations",
                ] {
                    assert_eq!(
                        after["tables"][table], before["tables"][table],
                        "{owner}: {table}"
                    );
                }
            }
        }
        drop(store);
        let reopened = TursoAgentStore::open_blocking(&state_dir).unwrap();
        assert_eq!(
            reopened.list_projects_blocking().unwrap()[0].git_mode,
            AgentGitMode::CommitAndPush
        );
        drop(reopened);
        fs::remove_dir_all(root).unwrap();
    }
}