story-kit: merge 297_story_improve_bot_status_command_formatting

This commit is contained in:
Dave
2026-03-19 09:36:58 +00:00
parent 170fd53808
commit 6353b12c1d

View File

@@ -178,6 +178,28 @@ fn strip_prefix_ci<'a>(text: &'a str, prefix: &str) -> Option<&'a str> {
// Pipeline status helpers (moved from bot.rs) // Pipeline status helpers (moved from bot.rs)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/// Format a short display label for a work item.
///
/// Extracts the leading numeric ID from the file stem (e.g. `"293"` from
/// `"293_story_register_all_bot_commands"`) and combines it with the human-
/// readable name from the front matter when available.
///
/// Examples:
/// - `("293_story_foo", Some("Register all bot commands"))` → `"293 — Register all bot commands"`
/// - `("293_story_foo", None)` → `"293"`
/// - `("no_number_here", None)` → `"no_number_here"`
fn story_short_label(stem: &str, name: Option<&str>) -> String {
let number = stem
.split('_')
.next()
.filter(|s| !s.is_empty() && s.chars().all(|c| c.is_ascii_digit()))
.unwrap_or(stem);
match name {
Some(n) => format!("{number}{n}"),
None => number.to_string(),
}
}
/// Read all story IDs and names from a pipeline stage directory. /// Read all story IDs and names from a pipeline stage directory.
fn read_stage_items( fn read_stage_items(
project_root: &std::path::Path, project_root: &std::path::Path,
@@ -243,10 +265,7 @@ pub fn build_pipeline_status(project_root: &std::path::Path, agents: &AgentPool)
out.push_str(" *(none)*\n"); out.push_str(" *(none)*\n");
} else { } else {
for (story_id, name) in &items { for (story_id, name) in &items {
let display = match name { let display = story_short_label(story_id, name.as_deref());
Some(n) => format!("{story_id}{n}"),
None => story_id.clone(),
};
if let Some(agent) = active_map.get(story_id) { if let Some(agent) = active_map.get(story_id) {
let model_str = config let model_str = config
.as_ref() .as_ref()
@@ -254,8 +273,8 @@ pub fn build_pipeline_status(project_root: &std::path::Path, agents: &AgentPool)
.and_then(|ac| ac.model.as_deref()) .and_then(|ac| ac.model.as_deref())
.unwrap_or("?"); .unwrap_or("?");
out.push_str(&format!( out.push_str(&format!(
"{display}{} ({}) [{}]\n", "{display}{} ({model_str})\n",
agent.agent_name, model_str, agent.status agent.agent_name
)); ));
} else { } else {
out.push_str(&format!("{display}\n")); out.push_str(&format!("{display}\n"));
@@ -667,6 +686,64 @@ mod tests {
assert_eq!(strip_prefix_ci("hello", "hello"), Some("")); assert_eq!(strip_prefix_ci("hello", "hello"), Some(""));
} }
// -- story_short_label --------------------------------------------------
#[test]
fn short_label_extracts_number_and_name() {
let label = story_short_label("293_story_register_all_bot_commands", Some("Register all bot commands"));
assert_eq!(label, "293 — Register all bot commands");
}
#[test]
fn short_label_number_only_when_no_name() {
let label = story_short_label("297_story_improve_bot_status_command_formatting", None);
assert_eq!(label, "297");
}
#[test]
fn short_label_falls_back_to_stem_when_no_numeric_prefix() {
let label = story_short_label("no_number_here", None);
assert_eq!(label, "no_number_here");
}
#[test]
fn short_label_does_not_include_underscore_slug() {
let label = story_short_label("293_story_register_all_bot_commands_in_the_command_registry", Some("Register all bot commands"));
assert!(
!label.contains("story_register"),
"label should not contain the slug portion: {label}"
);
}
// -- build_pipeline_status formatting -----------------------------------
#[test]
fn status_does_not_show_full_filename_stem() {
use std::io::Write;
use tempfile::TempDir;
let tmp = TempDir::new().unwrap();
let stage_dir = tmp.path().join(".story_kit/work/2_current");
std::fs::create_dir_all(&stage_dir).unwrap();
// Write a story file with a front-matter name
let story_path = stage_dir.join("293_story_register_all_bot_commands.md");
let mut f = std::fs::File::create(&story_path).unwrap();
writeln!(f, "---\nname: Register all bot commands\n---\n").unwrap();
let agents = AgentPool::new_test(3000);
let output = build_pipeline_status(tmp.path(), &agents);
assert!(
!output.contains("293_story_register_all_bot_commands"),
"output must not show full filename stem: {output}"
);
assert!(
output.contains("293 — Register all bot commands"),
"output must show number and title: {output}"
);
}
// -- commands registry -------------------------------------------------- // -- commands registry --------------------------------------------------
#[test] #[test]