fix(maestro): tool icon left of diff stat on sidebar meta line
ci / flake (push) Successful in 9m17s
ci / web (push) Successful in 1m9s
ci / rust (push) Successful in 3m55s

Meta line fragment order was command last, after the blocked-work diff
stat, so the tool icon sat right of the diff count instead of left.
Reorder to duration/detail/command/diff-stat in both web and TUI
sidebars per docs/SIDEBAR.md, and update the contract doc + TUI tests
to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Miguel Palhas
2026-09-02 17:17:44 +01:00
co-authored by Claude Sonnet 5
parent 21fc20b30a
commit c8ab4a531e
3 changed files with 16 additions and 9 deletions
+13 -6
View File
@@ -259,7 +259,7 @@ impl Sidebar {
pad_to_width(spans, width, base)
}
/// The adaptive second line: `[<duration>] [<detail>] [<blocked work> | exited] <command>`,
/// The adaptive second line: `[<duration>] [<detail>] <command> [<blocked work> | exited]`,
/// led by the activity rail (docs/SIDEBAR.md).
fn meta_row(&self, s: &Session, width: usize, focused: bool) -> Vec<Span<'static>> {
let now = Utc::now();
@@ -329,8 +329,8 @@ impl Sidebar {
budget,
));
}
spans.extend(tail);
spans.extend(fit_to_width(vec![command], command_w));
spans.extend(tail);
spans
}
}
@@ -927,9 +927,11 @@ mod tests {
let all = rows(&draw(&sb, 28, 8));
let idx = all.iter().position(|l| l.contains("claude")).unwrap();
let meta = content(&all[idx + 1]);
let ellipsis = meta.find('…').expect("truncated command must contain …");
let tail = meta.find("~120").expect("diff stat must survive: {meta:?}");
assert!(
meta.trim_end().ends_with('…'),
"truncated command must end with …: {meta:?}"
ellipsis < tail,
"command must truncate before the diff stat: {meta:?}"
);
assert!(
content(&all[idx + 2]).trim().is_empty(),
@@ -1131,7 +1133,7 @@ mod tests {
}
#[test]
fn blocked_warning_survives_before_a_truncated_command() {
fn blocked_warning_survives_after_a_truncated_command() {
let mut s = session_named(1, "name");
s.command = "a-program-name-that-cannot-fit".into();
s.blocked_work = Some(InTheWay {
@@ -1146,7 +1148,12 @@ mod tests {
let all = rows(&draw(&sb, 29, 6));
assert!(all[3].contains("~1"), "{:?}", all[3]);
let meta = content(&all[3]);
assert!(meta.ends_with('…'), "command must truncate: {meta:?}");
let ellipsis = meta.find('…').expect("command must truncate");
let tail = meta.find("~1").unwrap();
assert!(
ellipsis < tail,
"diff stat must follow the truncated command: {meta:?}"
);
}
#[test]
+2 -2
View File
@@ -37,7 +37,7 @@ itself is not.
Line 2 reads left to right:
```
[<duration>] [<detail>] [<diff stat> | exited] <command>
[<duration>] [<detail>] <command> [<diff stat> | exited]
```
Its minimum content is therefore just the command.
@@ -83,7 +83,7 @@ fragment; it no longer decides whether line 2 exists.
while an agent-reported state is in force (see Precedence): when the report
lapses at its TTL or is replaced, the detail goes with it. The detail
truncates with `…` ahead of the trailing fragments — a long detail never
pushes `<blocked work>`, `exited`, or `<command>` off the line, and neither
pushes `<command>`, `<blocked work>`, or `exited` off the line, and neither
client ever lets it wrap.
`<diff stat>` is the blocked-work breakdown (#83) in diff notation, replacing
+1 -1
View File
@@ -90,9 +90,9 @@ function metaLine(s: Session, now: number): string {
s.activity_detail
? `<span class="activity-detail">${escapeHtml(s.activity_detail)}</span>`
: "",
commandFragment(s.command),
blockers ? blockedFragment(blockers) : "",
dead ? `<span class="card-flag">exited</span>` : "",
commandFragment(s.command),
];
return `<span class="card-line2" data-activity="${slug}">${fragments.join("")}</span>`;
}