storkit: merge 378_story_status_command_shows_work_item_type_story_bug_spike_refactor_next_to_each_item
This commit is contained in:
@@ -16,23 +16,36 @@ pub(super) fn handle_status(ctx: &CommandContext) -> Option<String> {
|
||||
|
||||
/// 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.
|
||||
/// Extracts the leading numeric ID and optional type tag from the file stem
|
||||
/// (e.g. `"293"` and `"story"` from `"293_story_register_all_bot_commands"`)
|
||||
/// and combines them with the human-readable name from the front matter when
|
||||
/// available. Known types (`story`, `bug`, `spike`, `refactor`) are shown as
|
||||
/// bracketed labels; unknown or missing types are omitted silently.
|
||||
///
|
||||
/// Examples:
|
||||
/// - `("293_story_foo", Some("Register all bot commands"))` → `"293 — Register all bot commands"`
|
||||
/// - `("293_story_foo", None)` → `"293"`
|
||||
/// - `("293_story_foo", Some("Register all bot commands"))` → `"293 [story] — Register all bot commands"`
|
||||
/// - `("375_bug_foo", None)` → `"375 [bug]"`
|
||||
/// - `("293_story_foo", None)` → `"293 [story]"`
|
||||
/// - `("no_number_here", None)` → `"no_number_here"`
|
||||
pub(super) 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}"),
|
||||
let mut parts = stem.splitn(3, '_');
|
||||
let first = parts.next().unwrap_or(stem);
|
||||
let (number, type_label) = if !first.is_empty() && first.chars().all(|c| c.is_ascii_digit()) {
|
||||
let t = parts.next().and_then(|t| match t {
|
||||
"story" | "bug" | "spike" | "refactor" => Some(t),
|
||||
_ => None,
|
||||
});
|
||||
(first, t)
|
||||
} else {
|
||||
(stem, None)
|
||||
};
|
||||
let prefix = match type_label {
|
||||
Some(t) => format!("{number} [{t}]"),
|
||||
None => number.to_string(),
|
||||
};
|
||||
match name {
|
||||
Some(n) => format!("{prefix} — {n}"),
|
||||
None => prefix,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,13 +213,13 @@ mod tests {
|
||||
#[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");
|
||||
assert_eq!(label, "293 [story] — 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");
|
||||
assert_eq!(label, "297 [story]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -224,6 +237,37 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn short_label_shows_bug_type() {
|
||||
let label = story_short_label("375_bug_default_project_toml", Some("Default project.toml issue"));
|
||||
assert_eq!(label, "375 [bug] — Default project.toml issue");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn short_label_shows_spike_type() {
|
||||
let label = story_short_label("61_spike_filesystem_watcher_architecture", Some("Filesystem watcher architecture"));
|
||||
assert_eq!(label, "61 [spike] — Filesystem watcher architecture");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn short_label_shows_refactor_type() {
|
||||
let label = story_short_label("260_refactor_upgrade_libsqlite3_sys", Some("Upgrade libsqlite3-sys"));
|
||||
assert_eq!(label, "260 [refactor] — Upgrade libsqlite3-sys");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn short_label_omits_unknown_type() {
|
||||
let label = story_short_label("42_task_do_something", Some("Do something"));
|
||||
assert_eq!(label, "42 — Do something");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn short_label_no_type_when_only_id() {
|
||||
// Stem with only a numeric ID and no type segment
|
||||
let label = story_short_label("42", Some("Some item"));
|
||||
assert_eq!(label, "42 — Some item");
|
||||
}
|
||||
|
||||
// -- build_pipeline_status formatting -----------------------------------
|
||||
|
||||
#[test]
|
||||
@@ -248,8 +292,8 @@ mod tests {
|
||||
"output must not show full filename stem: {output}"
|
||||
);
|
||||
assert!(
|
||||
output.contains("293 — Register all bot commands"),
|
||||
"output must show number and title: {output}"
|
||||
output.contains("293 [story] — Register all bot commands"),
|
||||
"output must show number, type, and title: {output}"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -288,7 +332,7 @@ mod tests {
|
||||
let output = build_pipeline_status(tmp.path(), &agents);
|
||||
|
||||
assert!(
|
||||
output.contains("293 — Register all bot commands — $0.29"),
|
||||
output.contains("293 [story] — Register all bot commands — $0.29"),
|
||||
"output must show cost next to story: {output}"
|
||||
);
|
||||
}
|
||||
@@ -351,7 +395,7 @@ mod tests {
|
||||
let output = build_pipeline_status(tmp.path(), &agents);
|
||||
|
||||
assert!(
|
||||
output.contains("293 — Register all bot commands — $0.29"),
|
||||
output.contains("293 [story] — Register all bot commands — $0.29"),
|
||||
"output must show aggregated cost: {output}"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user