changed user choice for TODO stale check

user can ignore, mark stale or quit.
This commit is contained in:
Jochen
2025-11-21 12:35:14 +11:00
parent 84718223bc
commit 551a577ee1
5 changed files with 99 additions and 39 deletions

View File

@@ -10,6 +10,7 @@ use serial_test::serial;
struct MockUiWriter {
output: Arc<Mutex<Vec<String>>>,
prompt_responses: Arc<Mutex<Vec<bool>>>,
choice_responses: Arc<Mutex<Vec<usize>>>,
}
impl MockUiWriter {
@@ -17,6 +18,7 @@ impl MockUiWriter {
Self {
output: Arc::new(Mutex::new(Vec::new())),
prompt_responses: Arc::new(Mutex::new(Vec::new())),
choice_responses: Arc::new(Mutex::new(Vec::new())),
}
}
@@ -24,6 +26,10 @@ impl MockUiWriter {
self.prompt_responses.lock().unwrap().push(response);
}
fn set_choice_response(&self, response: usize) {
self.choice_responses.lock().unwrap().push(response);
}
fn get_output(&self) -> Vec<String> {
self.output.lock().unwrap().clone()
}
@@ -60,6 +66,10 @@ impl UiWriter for MockUiWriter {
self.output.lock().unwrap().push(format!("PROMPT: {}", message));
self.prompt_responses.lock().unwrap().pop().unwrap_or(true)
}
fn prompt_user_choice(&self, message: &str, options: &[&str]) -> usize {
self.output.lock().unwrap().push(format!("CHOICE: {} Options: {:?}", message, options));
self.choice_responses.lock().unwrap().pop().unwrap_or(0)
}
}
#[tokio::test]
@@ -92,7 +102,7 @@ async fn test_todo_staleness_check_matching_sha() {
#[tokio::test]
#[serial]
async fn test_todo_staleness_check_mismatch_sha_abort() {
async fn test_todo_staleness_check_mismatch_sha_ignore() {
let temp_dir = TempDir::new().unwrap();
let todo_path = temp_dir.path().join("todo.g3.md");
std::env::set_current_dir(&temp_dir).unwrap();
@@ -106,38 +116,7 @@ async fn test_todo_staleness_check_mismatch_sha_abort() {
config.agent.check_todo_staleness = true;
let ui_writer = MockUiWriter::new();
ui_writer.set_prompt_response(false); // Abort
let mut agent = Agent::new_autonomous(config, ui_writer).await.unwrap();
agent.set_requirements_sha(sha_req.to_string());
let tool_call = ToolCall {
tool: "todo_read".to_string(),
args: serde_json::json!({}),
};
let result = agent.execute_tool(&tool_call).await.unwrap();
assert!(result.contains("❌ User aborted due to stale TODO list."));
}
#[tokio::test]
#[serial]
async fn test_todo_staleness_check_mismatch_sha_continue() {
let temp_dir = TempDir::new().unwrap();
let todo_path = temp_dir.path().join("todo.g3.md");
std::env::set_current_dir(&temp_dir).unwrap();
let sha_file = "old_sha";
let sha_req = "new_sha";
let content = format!("{{{{Based on the requirements file with SHA256: {}}}}}\n- [ ] Task 1", sha_file);
std::fs::write(&todo_path, content).unwrap();
let mut config = Config::default();
config.agent.check_todo_staleness = true;
let ui_writer = MockUiWriter::new();
ui_writer.set_prompt_response(true); // Continue
let output_handle = ui_writer.clone(); // Clone to keep handle
ui_writer.set_choice_response(0); // Ignore
let mut agent = Agent::new_autonomous(config, ui_writer).await.unwrap();
agent.set_requirements_sha(sha_req.to_string());
@@ -149,12 +128,42 @@ async fn test_todo_staleness_check_mismatch_sha_continue() {
let result = agent.execute_tool(&tool_call).await.unwrap();
assert!(result.contains("📝 TODO list:"));
let output = output_handle.get_output();
let has_warning = output.iter().any(|s| s.contains("⚠️ TODO list is stale"));
assert!(has_warning, "Should have printed warning to UI");
}
#[tokio::test]
#[serial]
async fn test_todo_staleness_check_mismatch_sha_mark_stale() {
let temp_dir = TempDir::new().unwrap();
let todo_path = temp_dir.path().join("todo.g3.md");
std::env::set_current_dir(&temp_dir).unwrap();
let sha_file = "old_sha";
let sha_req = "new_sha";
let content = format!("{{{{Based on the requirements file with SHA256: {}}}}}\n- [ ] Task 1", sha_file);
std::fs::write(&todo_path, content).unwrap();
let mut config = Config::default();
config.agent.check_todo_staleness = true;
let ui_writer = MockUiWriter::new();
ui_writer.set_choice_response(1); // Mark as Stale
let mut agent = Agent::new_autonomous(config, ui_writer).await.unwrap();
agent.set_requirements_sha(sha_req.to_string());
let tool_call = ToolCall {
tool: "todo_read".to_string(),
args: serde_json::json!({}),
};
let result = agent.execute_tool(&tool_call).await.unwrap();
assert!(result.contains("⚠️ TODO list is stale"));
assert!(result.contains("Please regenerate"));
}
// Note: We cannot easily test "Quit" (index 2) because it calls std::process::exit(0)
// which would kill the test runner. We skip that test case here.
#[tokio::test]
#[serial]
async fn test_todo_staleness_check_disabled() {