feat: add unblock command and MCP tool to reset blocked stories

- Add `unblock` bot command (chat + web UI slash command) that clears the
  `blocked` flag and resets `retry_count` to 0 in story front matter
- Works across all pipeline stages (1_backlog through 6_archived)
- Returns confirmation with story name and ID, or clear error if story
  is not found or not blocked
- Expose `unblock_story` MCP tool for programmatic use by agents
- Make `chat::commands::unblock` module pub(crate) so story_tools can
  call `unblock_by_number`
- Add 8 unit tests covering registration, validation, core logic, and
  edge cases (not-found, not-blocked, any stage, story ID in response)
- Update MCP tools list test: 49 → 50 tools
This commit is contained in:
dave
2026-03-28 09:01:09 +00:00
parent 7652bbba9c
commit 6c6bc35785
4 changed files with 336 additions and 1 deletions
+18
View File
@@ -402,6 +402,24 @@ pub(super) fn tool_close_bug(args: &Value, ctx: &AppContext) -> Result<String, S
))
}
pub(super) fn tool_unblock_story(args: &Value, ctx: &AppContext) -> Result<String, String> {
let story_id = args
.get("story_id")
.and_then(|v| v.as_str())
.ok_or("Missing required argument: story_id")?;
let root = ctx.state.get_project_root()?;
// Extract the numeric prefix (e.g. "42" from "42_story_foo")
let story_number = story_id
.split('_')
.next()
.filter(|s| !s.is_empty() && s.chars().all(|c| c.is_ascii_digit()))
.ok_or_else(|| format!("Invalid story_id format: '{story_id}'. Expected a numeric prefix (e.g. '42_story_foo')."))?;
Ok(crate::chat::commands::unblock::unblock_by_number(&root, story_number))
}
pub(super) async fn tool_delete_story(args: &Value, ctx: &AppContext) -> Result<String, String> {
let story_id = args
.get("story_id")