huskies: merge 581_story_freeze_command_to_hold_a_story_at_its_current_stage_without_advancing

This commit is contained in:
dave
2026-04-15 17:57:56 +00:00
parent 2246278845
commit d235fd41ac
7 changed files with 365 additions and 2 deletions
+20
View File
@@ -57,6 +57,9 @@ pub struct StoryMetadata {
/// Story numbers this story depends on. Auto-assign will skip this story
/// until all dependencies have reached `5_done` or `6_archived`.
pub depends_on: Option<Vec<u32>>,
/// When `true`, the story is frozen: auto-assign skips it, the pipeline
/// does not advance it, and no mergemaster is spawned.
pub frozen: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -89,6 +92,8 @@ struct FrontMatter {
blocked: Option<bool>,
/// Story numbers this story depends on.
depends_on: Option<Vec<u32>>,
/// When `true`, the story is frozen.
frozen: Option<bool>,
}
pub fn parse_front_matter(contents: &str) -> Result<StoryMetadata, StoryMetaError> {
@@ -129,6 +134,7 @@ fn build_metadata(front: FrontMatter) -> StoryMetadata {
retry_count: front.retry_count,
blocked: front.blocked,
depends_on: front.depends_on,
frozen: front.frozen,
}
}
@@ -439,6 +445,20 @@ pub fn increment_retry_count_in_content(contents: &str) -> (String, u32) {
(updated, new_count)
}
/// Return `true` if the story has `frozen: true` in the content store.
///
/// Used by the pipeline advance code to suppress stage transitions for frozen stories.
pub fn is_story_frozen_in_store(story_id: &str) -> bool {
let contents = match crate::db::read_content(story_id) {
Some(c) => c,
None => return false,
};
parse_front_matter(&contents)
.ok()
.and_then(|m| m.frozen)
.unwrap_or(false)
}
/// Write `blocked: true` to story content (pure function).
pub fn write_blocked_in_content(contents: &str) -> String {
set_front_matter_field(contents, "blocked", "true")