From cb266e0071fed3fe3290012145e498b15b86c3cd Mon Sep 17 00:00:00 2001
From: th-kim0823
Date: Thu, 7 May 2026 21:49:47 +0900
Subject: [PATCH] fix(progress): eliminate duplicate bar frame per asset in TTY
mode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
AssetStarted now advances position (idx-1) and sets message together.
AssetFinished no longer updates the bar — Completed handles final
cleanup via finish_and_clear. Result: one bar frame per file instead
of two, eliminating the scrollback duplicate-line artifact.
---
crates/kebab-cli/src/progress.rs | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/crates/kebab-cli/src/progress.rs b/crates/kebab-cli/src/progress.rs
index 268f7f3..f91ed9e 100644
--- a/crates/kebab-cli/src/progress.rs
+++ b/crates/kebab-cli/src/progress.rs
@@ -144,6 +144,11 @@ impl ProgressDisplay {
media,
} => {
if let Some(bar) = self.bar.as_ref() {
+ // Advance position to N-1 (completed so far) and set the
+ // current-asset message in one atomic update, so TTY mode
+ // produces exactly one bar frame per file instead of two
+ // (AssetStarted + AssetFinished each triggered a redraw).
+ bar.set_position(u64::from(idx.saturating_sub(1)));
bar.set_message(format!("{media} {path}"));
}
if !tty && !quiet {
@@ -151,10 +156,10 @@ impl ProgressDisplay {
let _ = writeln!(err, "ingest: {idx}/{total} {media} {path}");
}
}
- IngestEvent::AssetFinished { idx, .. } => {
- if let Some(bar) = self.bar.as_ref() {
- bar.set_position(u64::from(*idx));
- }
+ IngestEvent::AssetFinished { .. } => {
+ // Position is advanced in AssetStarted; bar.finish_and_clear()
+ // in Completed handles the final state. No per-asset bar update
+ // here avoids the duplicate-frame artifact in TTY scrollback.
}
IngestEvent::Completed { counts } => {
if let Some(bar) = self.bar.take() {