story-kit: merge 287_story_rename_upcoming_pipeline_stage_to_backlog

This commit is contained in:
Dave
2026-03-18 14:31:12 +00:00
parent 967ebd7a84
commit df6f792214
26 changed files with 250 additions and 228 deletions

View File

@@ -409,7 +409,7 @@ fn scaffold_story_kit(root: &Path) -> Result<(), String> {
// Create the work/ pipeline directories, each with a .gitkeep so empty dirs survive git clone
let work_stages = [
"1_upcoming",
"1_backlog",
"2_current",
"3_qa",
"4_merge",
@@ -1085,7 +1085,7 @@ mod tests {
let dir = tempdir().unwrap();
scaffold_story_kit(dir.path()).unwrap();
let stages = ["1_upcoming", "2_current", "3_qa", "4_merge", "5_done", "6_archived"];
let stages = ["1_backlog", "2_current", "3_qa", "4_merge", "5_done", "6_archived"];
for stage in &stages {
let path = dir.path().join(".story_kit/work").join(stage);
assert!(path.is_dir(), "work/{} should be a directory", stage);

View File

@@ -78,7 +78,7 @@ pub fn is_config_file(path: &Path, git_root: &Path) -> bool {
/// Map a pipeline directory name to a (action, commit-message-prefix) pair.
fn stage_metadata(stage: &str, item_id: &str) -> Option<(&'static str, String)> {
let (action, prefix) = match stage {
"1_upcoming" => ("create", format!("story-kit: create {item_id}")),
"1_backlog" => ("create", format!("story-kit: create {item_id}")),
"2_current" => ("start", format!("story-kit: start {item_id}")),
"3_qa" => ("qa", format!("story-kit: queue {item_id} for QA")),
"4_merge" => ("merge", format!("story-kit: queue {item_id} for merge")),
@@ -111,7 +111,7 @@ fn stage_for_path(path: &Path) -> Option<String> {
.parent()
.and_then(|p| p.file_name())
.and_then(|n| n.to_str())?;
matches!(stage, "1_upcoming" | "2_current" | "3_qa" | "4_merge" | "5_done" | "6_archived")
matches!(stage, "1_backlog" | "2_current" | "3_qa" | "4_merge" | "5_done" | "6_archived")
.then(|| stage.to_string())
}
@@ -159,7 +159,7 @@ fn git_add_work_and_commit(git_root: &Path, message: &str) -> Result<bool, Strin
/// Intermediate stages (current, qa, merge, done) are transient pipeline state
/// that don't need to be committed — they're only relevant while the server is
/// running and are broadcast to WebSocket clients for real-time UI updates.
const COMMIT_WORTHY_STAGES: &[&str] = &["1_upcoming", "5_done", "6_archived"];
const COMMIT_WORTHY_STAGES: &[&str] = &["1_backlog", "5_done", "6_archived"];
/// Return `true` if changes in `stage` should be committed to git.
fn should_commit_stage(stage: &str) -> bool {
@@ -172,7 +172,7 @@ fn should_commit_stage(stage: &str) -> bool {
/// (they represent the destination of a move or a new file). Deletions are
/// captured by `git add -A .story_kit/work/` automatically.
///
/// Only terminal stages (`1_upcoming` and `6_archived`) trigger git commits.
/// Only terminal stages (`1_backlog` and `6_archived`) trigger git commits.
/// All stages broadcast a [`WatcherEvent`] so the frontend stays in sync.
fn flush_pending(
pending: &HashMap<PathBuf, String>,
@@ -574,13 +574,13 @@ mod tests {
fn flush_pending_commits_and_broadcasts_for_terminal_stage() {
let tmp = TempDir::new().unwrap();
init_git_repo(tmp.path());
let stage_dir = make_stage_dir(tmp.path(), "1_upcoming");
let stage_dir = make_stage_dir(tmp.path(), "1_backlog");
let story_path = stage_dir.join("42_story_foo.md");
fs::write(&story_path, "---\nname: test\n---\n").unwrap();
let (tx, mut rx) = tokio::sync::broadcast::channel(16);
let mut pending = HashMap::new();
pending.insert(story_path, "1_upcoming".to_string());
pending.insert(story_path, "1_backlog".to_string());
flush_pending(&pending, tmp.path(), &tx);
@@ -592,7 +592,7 @@ mod tests {
action,
commit_msg,
} => {
assert_eq!(stage, "1_upcoming");
assert_eq!(stage, "1_backlog");
assert_eq!(item_id, "42_story_foo");
assert_eq!(action, "create");
assert_eq!(commit_msg, "story-kit: create 42_story_foo");
@@ -660,7 +660,7 @@ mod tests {
#[test]
fn flush_pending_broadcasts_for_all_pipeline_stages() {
let stages = [
("1_upcoming", "create", "story-kit: create 10_story_x"),
("1_backlog", "create", "story-kit: create 10_story_x"),
("3_qa", "qa", "story-kit: queue 10_story_x for QA"),
("4_merge", "merge", "story-kit: queue 10_story_x for merge"),
("5_done", "done", "story-kit: done 10_story_x"),
@@ -792,10 +792,10 @@ mod tests {
}
#[test]
fn flush_pending_clears_merge_failure_when_moving_to_upcoming() {
fn flush_pending_clears_merge_failure_when_moving_to_backlog() {
let tmp = TempDir::new().unwrap();
init_git_repo(tmp.path());
let stage_dir = make_stage_dir(tmp.path(), "1_upcoming");
let stage_dir = make_stage_dir(tmp.path(), "1_backlog");
let story_path = stage_dir.join("51_story_reset.md");
fs::write(
&story_path,
@@ -805,14 +805,14 @@ mod tests {
let (tx, _rx) = tokio::sync::broadcast::channel(16);
let mut pending = HashMap::new();
pending.insert(story_path.clone(), "1_upcoming".to_string());
pending.insert(story_path.clone(), "1_backlog".to_string());
flush_pending(&pending, tmp.path(), &tx);
let contents = fs::read_to_string(&story_path).unwrap();
assert!(
!contents.contains("merge_failure"),
"merge_failure should be stripped when story lands in 1_upcoming"
"merge_failure should be stripped when story lands in 1_backlog"
);
}
@@ -937,7 +937,7 @@ mod tests {
#[test]
fn should_commit_stage_only_for_terminal_stages() {
// Terminal stages — should commit.
assert!(should_commit_stage("1_upcoming"));
assert!(should_commit_stage("1_backlog"));
assert!(should_commit_stage("5_done"));
assert!(should_commit_stage("6_archived"));
// Intermediate stages — broadcast-only, no commit.