From 35d4200417602a6360b41e6f8b401ec33a431257 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 15 Mar 2026 16:26:19 -0400 Subject: [PATCH] Fix truncate_goal: handle newlines, reuse for byte-unsafe inline truncation - Take first line before truncating to prevent multi-line goals from breaking table layout - Move goal field next to other manifest-sourced serialized fields - Replace byte-slicing truncation in df_from (panics on multibyte chars) with the char-safe truncate_goal helper Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/crates/fabro-workflows/src/cli/runs.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/crates/fabro-workflows/src/cli/runs.rs b/lib/crates/fabro-workflows/src/cli/runs.rs index 9a063f1b2..1cb177969 100644 --- a/lib/crates/fabro-workflows/src/cli/runs.rs +++ b/lib/crates/fabro-workflows/src/cli/runs.rs @@ -109,13 +109,13 @@ pub struct RunInfo { pub total_cost: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub host_repo_path: Option, + pub goal: String, #[serde(skip)] pub start_time_dt: Option>, #[serde(skip)] pub end_time: Option>, #[serde(skip)] pub path: PathBuf, - pub goal: String, #[serde(skip)] pub is_orphan: bool, } @@ -464,9 +464,10 @@ fn short_run_id(id: &str) -> &str { } fn truncate_goal(goal: &str, max_len: usize) -> String { - let chars: Vec = goal.chars().collect(); + let line = goal.lines().next().unwrap_or(""); + let chars: Vec = line.chars().collect(); if chars.len() <= max_len { - return goal.to_string(); + return line.to_string(); } let truncated: String = chars[..max_len - 3].iter().collect(); format!("{truncated}...") @@ -787,11 +788,7 @@ pub fn df_from(args: &DfArgs, data_dir: &Path, runs_base: &Path, logs_base: &Pat .iter() .map(|detail| { let run_id_display = short_run_id(&detail.run_id); - let workflow_display = if detail.workflow_name.len() > 16 { - format!("{}...", &detail.workflow_name[..13]) - } else { - detail.workflow_name.clone() - }; + let workflow_display = truncate_goal(&detail.workflow_name, 16); let age = if let Some(dt) = detail.start_time_dt { let dur = now.signed_duration_since(dt); if dur.num_days() > 0 {