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

@@ -16,9 +16,9 @@ pub(super) fn item_type_from_id(item_id: &str) -> &'static str {
}
}
/// Return the source directory path for a work item (always work/1_upcoming/).
/// Return the source directory path for a work item (always work/1_backlog/).
fn item_source_dir(project_root: &Path, _item_id: &str) -> PathBuf {
project_root.join(".story_kit").join("work").join("1_upcoming")
project_root.join(".story_kit").join("work").join("1_backlog")
}
/// Return the done directory path for a work item (always work/5_done/).
@@ -26,10 +26,10 @@ fn item_archive_dir(project_root: &Path, _item_id: &str) -> PathBuf {
project_root.join(".story_kit").join("work").join("5_done")
}
/// Move a work item (story, bug, or spike) from `work/1_upcoming/` to `work/2_current/`.
/// Move a work item (story, bug, or spike) from `work/1_backlog/` to `work/2_current/`.
///
/// Idempotent: if the item is already in `2_current/`, returns Ok without committing.
/// If the item is not found in `1_upcoming/`, logs a warning and returns Ok.
/// If the item is not found in `1_backlog/`, logs a warning and returns Ok.
pub fn move_story_to_current(project_root: &Path, story_id: &str) -> Result<(), String> {
let sk = project_root.join(".story_kit").join("work");
let current_dir = sk.join("2_current");
@@ -219,16 +219,16 @@ pub fn move_story_to_qa(project_root: &Path, story_id: &str) -> Result<(), Strin
Ok(())
}
/// Move a bug from `work/2_current/` or `work/1_upcoming/` to `work/5_done/` and auto-commit.
/// Move a bug from `work/2_current/` or `work/1_backlog/` to `work/5_done/` and auto-commit.
///
/// * If the bug is in `2_current/`, it is moved to `5_done/` and committed.
/// * If the bug is still in `1_upcoming/` (never started), it is moved directly to `5_done/`.
/// * If the bug is still in `1_backlog/` (never started), it is moved directly to `5_done/`.
/// * If the bug is already in `5_done/`, this is a no-op (idempotent).
/// * If the bug is not found anywhere, an error is returned.
pub fn close_bug_to_archive(project_root: &Path, bug_id: &str) -> Result<(), String> {
let sk = project_root.join(".story_kit").join("work");
let current_path = sk.join("2_current").join(format!("{bug_id}.md"));
let upcoming_path = sk.join("1_upcoming").join(format!("{bug_id}.md"));
let backlog_path = sk.join("1_backlog").join(format!("{bug_id}.md"));
let archive_dir = item_archive_dir(project_root, bug_id);
let archive_path = archive_dir.join(format!("{bug_id}.md"));
@@ -238,11 +238,11 @@ pub fn close_bug_to_archive(project_root: &Path, bug_id: &str) -> Result<(), Str
let source_path = if current_path.exists() {
current_path.clone()
} else if upcoming_path.exists() {
upcoming_path.clone()
} else if backlog_path.exists() {
backlog_path.clone()
} else {
return Err(format!(
"Bug '{bug_id}' not found in work/2_current/ or work/1_upcoming/. Cannot close bug."
"Bug '{bug_id}' not found in work/2_current/ or work/1_backlog/. Cannot close bug."
));
};
@@ -269,15 +269,15 @@ mod tests {
use std::fs;
let tmp = tempfile::tempdir().unwrap();
let root = tmp.path();
let upcoming = root.join(".story_kit/work/1_upcoming");
let backlog = root.join(".story_kit/work/1_backlog");
let current = root.join(".story_kit/work/2_current");
fs::create_dir_all(&upcoming).unwrap();
fs::create_dir_all(&backlog).unwrap();
fs::create_dir_all(&current).unwrap();
fs::write(upcoming.join("10_story_foo.md"), "test").unwrap();
fs::write(backlog.join("10_story_foo.md"), "test").unwrap();
move_story_to_current(root, "10_story_foo").unwrap();
assert!(!upcoming.join("10_story_foo.md").exists());
assert!(!backlog.join("10_story_foo.md").exists());
assert!(current.join("10_story_foo.md").exists());
}
@@ -295,25 +295,25 @@ mod tests {
}
#[test]
fn move_story_to_current_noop_when_not_in_upcoming() {
fn move_story_to_current_noop_when_not_in_backlog() {
let tmp = tempfile::tempdir().unwrap();
assert!(move_story_to_current(tmp.path(), "99_missing").is_ok());
}
#[test]
fn move_bug_to_current_moves_from_upcoming() {
fn move_bug_to_current_moves_from_backlog() {
use std::fs;
let tmp = tempfile::tempdir().unwrap();
let root = tmp.path();
let upcoming = root.join(".story_kit/work/1_upcoming");
let backlog = root.join(".story_kit/work/1_backlog");
let current = root.join(".story_kit/work/2_current");
fs::create_dir_all(&upcoming).unwrap();
fs::create_dir_all(&backlog).unwrap();
fs::create_dir_all(&current).unwrap();
fs::write(upcoming.join("1_bug_test.md"), "# Bug 1\n").unwrap();
fs::write(backlog.join("1_bug_test.md"), "# Bug 1\n").unwrap();
move_story_to_current(root, "1_bug_test").unwrap();
assert!(!upcoming.join("1_bug_test.md").exists());
assert!(!backlog.join("1_bug_test.md").exists());
assert!(current.join("1_bug_test.md").exists());
}
@@ -335,17 +335,17 @@ mod tests {
}
#[test]
fn close_bug_moves_from_upcoming_when_not_started() {
fn close_bug_moves_from_backlog_when_not_started() {
use std::fs;
let tmp = tempfile::tempdir().unwrap();
let root = tmp.path();
let upcoming = root.join(".story_kit/work/1_upcoming");
fs::create_dir_all(&upcoming).unwrap();
fs::write(upcoming.join("3_bug_test.md"), "# Bug 3\n").unwrap();
let backlog = root.join(".story_kit/work/1_backlog");
fs::create_dir_all(&backlog).unwrap();
fs::write(backlog.join("3_bug_test.md"), "# Bug 3\n").unwrap();
close_bug_to_archive(root, "3_bug_test").unwrap();
assert!(!upcoming.join("3_bug_test.md").exists());
assert!(!backlog.join("3_bug_test.md").exists());
assert!(root.join(".story_kit/work/5_done/3_bug_test.md").exists());
}