--- phase: P9 component: kebab-cli task_id: p9-fb-26 title: "Ingest 로그 출력 일관성 (in-place vs 새 줄 혼재)" status: merged target_version: 0.3.0 depends_on: [p9-fb-02] unblocks: [] contract_source: ../../docs/superpowers/specs/2026-04-27-kebab-final-form-design.md contract_sections: [§7 ingest, §10 UX, §2.4a IngestEvent] source_feedback: 사용자 도그푸딩 2026-05-05 — `kebab ingest` 진행 로그가 어떨 땐 새 라인으로, 어떨 땐 기존 라인 in-place 갱신으로 나와 일관성 떨어짐. --- # p9-fb-26 — Ingest 로그 출력 일관성 > ⏳ **백로그 only — 미구현.** 본 spec 은 도그푸딩 피드백 skeleton. 구현 착수 전 [superpowers:brainstorming](../../docs/superpowers/) 으로 설계 단계 선행 필요. 옵션 A/B/C 중 결정 + behavior contract 확정 후 implementation PR 진행. ## 증상 `kebab ingest` 실행 중 진행 출력이 두 패턴 혼재: - **TTY**: indicatif `ProgressBar` 단일 라인 in-place 갱신 (`ScanStarted` / `ScanCompleted` / `AssetStarted` / `AssetFinished`). 마지막 `Completed` / `Aborted` summary 만 별도 새 라인. - **non-TTY (pipe / less / CI)**: 매 event 마다 `writeln!` 새 라인. - 같은 세션 안에서도 환경 변경 (예: `kebab ingest 2>&1 | tee log`) 시 출력 형식 바뀜. 사용자 인지: "어떨 땐 새 라인, 어떨 땐 기존 라인 업데이트". 시각적 노이즈 + 스크롤백에 진행 흔적 일부만 남거나 전체 남는 비대칭. ## 원인 [crates/kebab-cli/src/progress.rs:99-188](../../crates/kebab-cli/src/progress.rs#L99-L188): - TTY branch 는 `bar.set_message` / `bar.set_position` 으로 단일 라인 갱신. - non-TTY branch (`if !tty { writeln!(err, ...) }`) 가 모든 event 마다 추가 라인. - Completed / Aborted 는 TTY 에서도 `writeln!` 항상 호출 — bar finish 후 summary 한 줄. ## Goal 진행 로그의 출력 형식을 환경 무관하게 예측 가능하게 만든다. 사용자는 한 가지 형식을 보고 다른 환경에서도 같은 형식을 기대해야 함. ## Behavior contract (제안 — brainstorming 단계, 머지 전 사용자 확인) 옵션 A — **TTY = in-place, non-TTY = append-only, 둘 다 명시적**: - TTY: 진행 라인은 in-place, summary 도 마지막에 같은 라인 commit (현재 처럼 새 줄 X) 또는 한 줄 띄우고 명시적 final. - non-TTY: 매 event 한 줄 (현재 동작 유지) — pipe / log redirect 에서 진행 흔적 남는 게 정답. - summary 라인은 두 모드 동일한 prefix (`ingest: complete (...)` / `ingest: aborted (...)`) 로 통일. 옵션 B — **항상 append-only**: - TTY 에서도 spinner 끄고 매 event 새 라인. 단순, 진행 흔적 보존. - 단점: bar UX 손실 — long ingest 에서 화면 가득. 옵션 C — **항상 in-place (TTY 만)**: - non-TTY 면 마지막 summary 한 줄만, 중간 event silent. - 단점: CI / log redirect 에서 진행 알 수 없음. 권장: **옵션 A** — 환경별 의미 명확, 두 형식 다 의도된 것임을 README 에 명시. ## 검증 / 테스트 - `kebab ingest` TTY 모드: spinner 한 라인만 차지, 종료 후 summary 한 줄. - `kebab ingest 2>&1 | cat`: append-only 형식, 매 asset / scan event 한 줄. - `kebab ingest --json`: 기존 ndjson 동작 유지 (영향 없음). - snapshot test: non-TTY 스트림 포맷 안정. ## 관련 항목 - p9-fb-01 / p9-fb-02 (progress 인프라). 본 항목은 그 위의 일관성 follow-up. - 사용자 visible surface — README **명령** 표 / Quick start 의 ingest 출력 예시 갱신 필요. ## Risks / notes - indicatif `ProgressDrawTarget::stderr()` 가 일부 터미널 (TUI multiplexer, 일부 ssh client) 에서 in-place 갱신 fallback 으로 새 라인 그릴 수 있음 — 조사 필요. - CI 가 TTY-emulating wrapper (예: GitHub Actions 일부) 면 의도 안 한 in-place 모드 진입 가능. 명시적 `KEBAB_PROGRESS=plain` env override 검토.