diff --git a/server/src/chat/commands/show.rs b/server/src/chat/commands/show.rs index be22f484..881f9998 100644 --- a/server/src/chat/commands/show.rs +++ b/server/src/chat/commands/show.rs @@ -2,6 +2,62 @@ use super::CommandContext; +/// Strip YAML front matter and return a summary of useful fields + the remaining body. +fn strip_front_matter(text: &str) -> (String, String) { + let trimmed = text.trim_start(); + if !trimmed.starts_with("---") { + return (String::new(), text.to_string()); + } + + // Find the closing --- + if let Some(end) = trimmed[3..].find("\n---") { + let yaml_block = &trimmed[3..3 + end].trim(); + let body = &trimmed[3 + end + 4..]; // skip past closing --- + + // Extract useful fields from YAML (simple line-based parsing) + let mut parts = Vec::new(); + for line in yaml_block.lines() { + let line = line.trim(); + if line.starts_with("depends_on:") { + let val = line.trim_start_matches("depends_on:").trim(); + if !val.is_empty() && val != "[]" { + parts.push(format!("**Depends on:** {val}")); + } + } else if line.starts_with("agent:") { + let val = line.trim_start_matches("agent:").trim().trim_matches('"'); + if !val.is_empty() { + parts.push(format!("**Agent:** {val}")); + } + } else if line.starts_with("blocked:") { + let val = line.trim_start_matches("blocked:").trim(); + if val == "true" { + parts.push("**Blocked:** yes".to_string()); + } + } else if line.starts_with("retry_count:") { + let val = line.trim_start_matches("retry_count:").trim(); + if val != "0" && !val.is_empty() { + parts.push(format!("**Retries:** {val}")); + } + } else if line.starts_with("qa:") { + let val = line.trim_start_matches("qa:").trim().trim_matches('"'); + if val == "human" { + parts.push("**QA:** human review required".to_string()); + } + } else if line.starts_with("merge_failure:") { + let val = line.trim_start_matches("merge_failure:").trim().trim_matches('"'); + if !val.is_empty() { + parts.push(format!("**Merge failure:** {val}")); + } + } + } + + (parts.join(" · "), body.to_string()) + } else { + // No closing ---, return as-is + (String::new(), text.to_string()) + } +} + /// Display the full markdown text of a work item identified by its numeric ID. /// /// Lookup priority: CRDT → content store → filesystem (Story 512). @@ -38,10 +94,13 @@ pub(super) fn handle_show(ctx: &CommandContext) -> Option { format!("Story {story_id} found in pipeline but its content is unavailable.") }); + // Strip front matter block and extract useful metadata to show inline. + let (front_matter_summary, body) = strip_front_matter(&text); + // Convert markdown headings to bold text for consistent rendering across // Matrix clients. Element X doesn't style

tags distinctly, but bold // text renders consistently everywhere. - let formatted = text + let formatted = body .lines() .map(|line| { let trimmed = line.trim_start(); @@ -58,7 +117,11 @@ pub(super) fn handle_show(ctx: &CommandContext) -> Option { .collect::>() .join("\n"); - Some(formatted) + if front_matter_summary.is_empty() { + Some(formatted.trim().to_string()) + } else { + Some(format!("{front_matter_summary}\n{}", formatted.trim())) + } } #[cfg(test)]