Ctrl-C / Esc 가 ingest 를 즉시 중단. 현재 in-flight asset 마무리 후
이후 asset 미실행, IngestEvent::Aborted { partial_counts } 발신,
Ok(IngestReport) 정상 반환 (Err 아님). 부분 commit 보존, 다음 ingest
가 idempotent 재개.
신규 facade: kebab-app::ingest_with_config_cancellable(.., progress,
cancel: Option<Arc<AtomicBool>>). 기존 _progress 가 cancel=None
forwarding wrapper. asset loop 시작 boundary 마다 atomic load —
true 면 break + Aborted emit + 정상 종료. Lock 없음.
CLI: ctrlc crate 신규 dep. SIGINT handler 가 첫 신호에 cancel.store(true)
+ stderr hint, 두 번째 신호에 std::process::exit(130) (canonical SIGINT
exit code). install_sigint_cancel() helper 가 Arc<AtomicBool> 반환,
Cmd::Ingest 가 facade 에 전달.
TUI: IngestState 에 cancel: Arc<AtomicBool> field 추가 (회차 1 review
결과의 reshape 정확). start_ingest 가 둘 다 만들어 worker 에 clone
move. cancel_running_ingest(&app) helper — Esc / Ctrl-C 가
ingest 진행 중일 때만 cancel 우선, 그 외에는 quit.
Test:
- 3 facade integration (cancel-before / cancel-mid / no-cancel
default).
- 3 tui lib unit (cancel_running_ingest no-state / in-flight /
terminated).
Plan 갱신: p9-fb-04 status planned → in_progress. 머지 후 한 줄
commit 으로 completed flip.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2.3 KiB
2.3 KiB
phase, component, task_id, title, status, depends_on, unblocks, contract_source, contract_sections, source_feedback
| phase | component | task_id | title | status | depends_on | unblocks | contract_source | contract_sections | source_feedback | ||
|---|---|---|---|---|---|---|---|---|---|---|---|
| P9 | kebab-app + kebab-cli + kebab-tui | p9-fb-04 | Cooperative ingest cancellation (Ctrl-C / Esc) | in_progress |
|
../../docs/superpowers/specs/2026-04-27-kebab-final-form-design.md |
|
p9-dogfooding-feedback.md item 2 |
p9-fb-04 — Ingest cancellation
Goal
ingest 가 사용자 cancel 신호 (Ctrl-C / Esc) 받으면 step boundary 에서 즉시 중단. 부분 진행은 SQLite 에 commit 된 상태 유지 — resume 은 idempotent.
Allowed dependencies
std::sync::atomic::AtomicBool(Arc 공유). 외부 crate X.
Public surface
#[doc(hidden)]
pub fn ingest_with_config_cancellable(
config: kebab_config::Config,
scope: SourceScope,
summary_only: bool,
progress: Option<Sender<IngestEvent>>,
cancel: Option<Arc<AtomicBool>>,
) -> anyhow::Result<IngestReport>;
기존 ingest_with_config_progress (p9-fb-01) 가 cancel=None forwarding.
Behavior contract
- check 위치 (step boundary): asset loop iteration 시작, embed batch 시작, vector upsert 직후. 가장 긴 wait 인 LLM 호출 (OCR / caption) 도 가능하면 token boundary 에서 check (Ollama HTTP 응답 stream 이라 partial cancel 가능).
- cancel triggered 시: 현재 in-flight asset 마무리 (rollback 하면 idempotent 깨질 수 있음 — commit 후 종료가 안전), 이후 asset 미실행,
IngestEvent::Aborted { partial_counts }발신,Ok(IngestReport)반환 (Err 가 아님 — 정상 종료의 한 형태). - CLI
kebab ingest: Ctrl-C SIGINT handler 가cancel.store(true, Ordering::Relaxed). 두 번째 Ctrl-C 는 hard exit. - TUI:
Esc(ingest 진행 중에만) 또는Ctrl-C가 cancel signal. p9-fb-03 의IngestState.cancel_tx와 wiring.
Test plan
| kind | description |
|---|---|
| unit | cancel=true set 후 다음 step 에서 Aborted event |
| integration | 100 md fixture, idx=10 cancel → DB 에 10 docs 만 commit, idempotent re-ingest 가능 |
DoD
cargo test -p kebab-app통과- CLI Ctrl-C handler test
- TUI Esc cancel test
- HOTFIXES X (신규)
- README — Ctrl-C 동작 명시
Out of scope
- resume from checkpoint (현재는 idempotent re-run 으로 충분)
- embed / RAG streaming cancel (별도 task)