diff --git a/server/src/chat/commands/unblock.rs b/server/src/chat/commands/unblock.rs index a07d9588..570b1917 100644 --- a/server/src/chat/commands/unblock.rs +++ b/server/src/chat/commands/unblock.rs @@ -6,8 +6,7 @@ use super::CommandContext; use crate::io::story_metadata::{ - clear_front_matter_field, clear_front_matter_field_in_content, parse_front_matter, - set_front_matter_field, + clear_front_matter_field_in_content, parse_front_matter, set_front_matter_field, }; use std::path::Path; @@ -34,9 +33,9 @@ pub(super) fn handle_unblock(ctx: &CommandContext) -> Option { /// Returns a Markdown-formatted response string suitable for all transports. /// Also used by the MCP `unblock` tool. /// -/// Lookup priority: CRDT → content store → filesystem (Story 512). +/// Lookup priority: CRDT → content store. pub(crate) fn unblock_by_number(project_root: &Path, story_number: &str) -> String { - let (story_id, _stage_dir, path, _content) = + let (story_id, _, _, _) = match crate::chat::lookup::find_story_by_number(project_root, story_number) { Some(found) => found, None => { @@ -44,15 +43,7 @@ pub(crate) fn unblock_by_number(project_root: &Path, story_number: &str) -> Stri } }; - // Prefer DB-backed unblock when the story is in the content store. - // Note: `content` may have come from the filesystem fallback in - // `find_story_by_number`, so we must re-check the DB rather than - // relying on `content.is_some()` alone. - if crate::db::read_content(&story_id).is_some() { - unblock_by_story_id(&story_id) - } else { - unblock_by_path(&path, &story_id) - } + unblock_by_story_id(&story_id) } /// Unblock a story using the content store (DB-backed). @@ -105,64 +96,6 @@ fn unblock_by_story_id(story_id: &str) -> String { ) } -/// Core unblock logic: reset blocked state for a known story file path. -/// -/// Reads front matter, verifies the story is blocked, clears the `blocked` -/// flag, and resets `retry_count` to 0. Also used by the MCP `unblock` tool -/// when the caller has already resolved the story path from a full `story_id`. -pub(crate) fn unblock_by_path(path: &Path, story_id: &str) -> String { - let contents = match std::fs::read_to_string(path) { - Ok(c) => c, - Err(e) => return format!("Failed to read story file: {e}"), - }; - - 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(); - - let has_blocked = meta.blocked == Some(true); - let has_merge_failure = meta.merge_failure.is_some(); - - if !has_blocked && !has_merge_failure { - return format!("**{story_name}** ({story_id}) is not blocked. Nothing to unblock."); - } - - // Clear the blocked flag if present. - if has_blocked && let Err(e) = clear_front_matter_field(path, "blocked") { - return format!("Failed to clear blocked flag on **{story_id}**: {e}"); - } - - // Clear merge_failure if present. - if has_merge_failure && let Err(e) = clear_front_matter_field(path, "merge_failure") { - return format!("Failed to clear merge_failure on **{story_id}**: {e}"); - } - - // Reset retry_count to 0 (re-read the updated file, modify, write). - let updated_contents = match std::fs::read_to_string(path) { - Ok(c) => c, - Err(e) => return format!("Failed to re-read story file after unblocking: {e}"), - }; - let with_retry_reset = set_front_matter_field(&updated_contents, "retry_count", "0"); - if let Err(e) = std::fs::write(path, &with_retry_reset) { - return format!("Failed to reset retry_count on **{story_id}**: {e}"); - } - - let mut cleared = Vec::new(); - if has_blocked { - cleared.push("blocked"); - } - if has_merge_failure { - cleared.push("merge_failure"); - } - format!( - "Unblocked **{story_name}** ({story_id}). Cleared: {}. Retry count reset to 0.", - cleared.join(", ") - ) -} - // --------------------------------------------------------------------------- // Tests // ---------------------------------------------------------------------------