huskies: merge 878

This commit is contained in:
dave
2026-04-29 23:48:30 +00:00
parent 1d86202abb
commit 8fc581ad6b
9 changed files with 413 additions and 51 deletions
+24 -47
View File
@@ -38,30 +38,13 @@ pub(crate) fn freeze_by_number(project_root: &Path, story_number: &str) -> Strin
}
fn freeze_by_story_id(story_id: &str) -> String {
let contents = match crate::db::read_content(story_id) {
Some(c) => c,
None => return format!("Failed to read story content for **{story_id}**"),
};
let story_name = resolve_story_name(story_id);
let meta = match parse_front_matter(&contents) {
Ok(m) => m,
Err(e) => return format!("Failed to parse front matter for **{story_id}**: {e}"),
};
let story_name = meta.name.as_deref().unwrap_or(story_id).to_string();
// Check if already frozen via the typed stage.
if crate::pipeline_state::read_typed(story_id)
.ok()
.flatten()
.map(|i| i.stage.is_frozen())
.unwrap_or(false)
{
return format!("**{story_name}** ({story_id}) is already frozen.");
}
match crate::pipeline_state::transition_to_frozen(story_id) {
Ok(_) => format!(
match crate::service::work_item::freeze::freeze(story_id) {
Ok(crate::service::work_item::FreezeStatus::AlreadyFrozen) => {
format!("**{story_name}** ({story_id}) is already frozen.")
}
Ok(crate::service::work_item::FreezeStatus::Frozen) => format!(
"Frozen **{story_name}** ({story_id}). Pipeline advancement and auto-assign suppressed until unfrozen."
),
Err(e) => format!("Failed to freeze **{story_name}** ({story_id}): {e}"),
@@ -97,37 +80,31 @@ pub(crate) fn unfreeze_by_number(project_root: &Path, story_number: &str) -> Str
}
fn unfreeze_by_story_id(story_id: &str) -> String {
let contents = match crate::db::read_content(story_id) {
Some(c) => c,
None => return format!("Failed to read story content for **{story_id}**"),
};
let story_name = resolve_story_name(story_id);
let meta = match parse_front_matter(&contents) {
Ok(m) => m,
Err(e) => return format!("Failed to parse front matter for **{story_id}**: {e}"),
};
let story_name = meta.name.as_deref().unwrap_or(story_id).to_string();
// Check frozen via typed stage.
let is_frozen = crate::pipeline_state::read_typed(story_id)
.ok()
.flatten()
.map(|i| i.stage.is_frozen())
.unwrap_or(false);
if !is_frozen {
return format!("**{story_name}** ({story_id}) is not frozen. Nothing to unfreeze.");
}
match crate::pipeline_state::transition_to_unfrozen(story_id) {
Ok(_) => {
match crate::service::work_item::freeze::unfreeze(story_id) {
Ok(crate::service::work_item::UnfreezeStatus::NotFrozen) => {
format!("**{story_name}** ({story_id}) is not frozen. Nothing to unfreeze.")
}
Ok(crate::service::work_item::UnfreezeStatus::Unfrozen) => {
format!("Unfrozen **{story_name}** ({story_id}). Normal pipeline behaviour resumed.")
}
Err(e) => format!("Failed to unfreeze **{story_name}** ({story_id}): {e}"),
}
}
/// Look up the display name for a story by reading its content store entry.
///
/// Falls back to `story_id` if the content is missing or the front matter
/// cannot be parsed.
fn resolve_story_name(story_id: &str) -> String {
crate::db::read_content(story_id)
.as_deref()
.and_then(|c| parse_front_matter(c).ok())
.and_then(|m| m.name)
.unwrap_or_else(|| story_id.to_string())
}
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------