story-kit: merge 311_story_server_enforced_retry_limits_for_failed_merge_and_empty_diff_stories

This commit is contained in:
Dave
2026-03-19 16:34:11 +00:00
parent 662e00f94a
commit 3b887e3085
9 changed files with 346 additions and 65 deletions

View File

@@ -219,6 +219,19 @@ pub async fn remove_worktree_by_story_id(
}
/// List all worktrees under `{project_root}/.story_kit/worktrees/`.
/// Find the worktree path for a given story ID, if it exists.
pub fn find_worktree_path(project_root: &Path, story_id: &str) -> Option<PathBuf> {
let wt_path = project_root
.join(".story_kit")
.join("worktrees")
.join(story_id);
if wt_path.is_dir() {
Some(wt_path)
} else {
None
}
}
pub fn list_worktrees(project_root: &Path) -> Result<Vec<WorktreeListEntry>, String> {
let worktrees_dir = project_root.join(".story_kit").join("worktrees");
if !worktrees_dir.exists() {
@@ -510,6 +523,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
// Should complete without panic
run_setup_commands(tmp.path(), &config).await;
@@ -530,6 +544,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
// Should complete without panic
run_setup_commands(tmp.path(), &config).await;
@@ -550,6 +565,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
// Setup command failures are non-fatal — should not panic or propagate
run_setup_commands(tmp.path(), &config).await;
@@ -570,6 +586,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
// Teardown failures are best-effort — should not propagate
assert!(run_teardown_commands(tmp.path(), &config).await.is_ok());
@@ -589,6 +606,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
let info = create_worktree(&project_root, "42_fresh_test", &config, 3001)
.await
@@ -615,6 +633,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
// First creation
let _info1 = create_worktree(&project_root, "43_reuse_test", &config, 3001)
@@ -657,6 +676,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
let result = remove_worktree_by_story_id(tmp.path(), "99_nonexistent", &config).await;
@@ -682,6 +702,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
create_worktree(&project_root, "88_remove_by_id", &config, 3001)
.await
@@ -738,6 +759,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
// Even though setup commands fail, create_worktree must succeed
// so the agent can start and fix the problem itself.
@@ -766,6 +788,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
// First creation — no setup commands, should succeed
create_worktree(&project_root, "173_reuse_fail", &empty_config, 3001)
@@ -784,6 +807,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
// Second call — worktree exists, setup commands fail, must still succeed
let result =
@@ -809,6 +833,7 @@ mod tests {
default_qa: "server".to_string(),
default_coder_model: None,
max_coders: None,
max_retries: 2,
};
let info = create_worktree(&project_root, "77_remove_async", &config, 3001)
.await