feat(ingest): asset 내부 phase 진행 로깅 (asset_chunked/expansion_progress/asset_timings) #201

Merged
altair823 merged 4 commits from feat/ingest-progress-detail into main 2026-06-02 17:26:50 +00:00
Owner

요약

ingest 진행 이벤트가 asset(문서) 단위(asset_started/asset_finished)뿐이라, 한 문서 내부의 parse / chunk / expansion(별칭 LLM, 청크당 순차 호출) / embed / store 가 깜깜했다. expansion 은 청크당 14s(원격 GPU Ollama)이고 큰 문서는 청크 수백~천 개 → 그 한 문서에서 수십 분이 걸리는데 진행바는 1/N 에 멈춘 듯 보여 사용자가 병목을 못 봤다.

이 PR 은 asset 내부 phase 를 노출해 어디서 시간이 가는지 즉시 보이게 한다 — 청크 수 · expansion 라이브 카운터 · phase 별 소요시간. wire ingest_progress.v1additive(backward-compat) 유지.

설계: docs/superpowers/specs/ 없음(진행-로깅 계측, design §2.4a 의 "future embed-batch events" 자리 확장). 동기/벤치 근거는 tasks/HOTFIXES.md 2026-06-02 항목.

변경

  • IngestEvent 신규 변이 3개 (#[serde(tag="kind")] → wire v1 호환):
    • asset_chunked { idx, total, chunks } — 청킹 직후(expansion/embed 전) 청크 수 즉시 노출. markdown/image/pdf 모두.
    • expansion_progress { idx, total, done, chunks } — expansion 루프 중 스로틀(25청크 또는 ≥1s). 캐시 히트도 done 포함. 채널 폭주 방지.
    • asset_timings { idx, total, parse_ms, chunk_ms, expansion_ms, embed_ms, store_ms } — markdown 경로 phase 별 소요시간.
  • ingest_one_asset/_image_asset/_pdf_assetidx,total 스레딩 + markdown 경로 phase 타이머.
  • CLI progress.rs 렌더 — → N chunks, 별칭 확장 done/chunks, ⏱ parse … · store …. --json 자동, --quiet 억제.
  • wire schema doc additive, TUI reducer no-op arm, 버전 0.23.1 → 0.24.0.

검증

  • cargo clippy --workspace --all-targets -j 4 -- -D warnings → exit 0.
  • cargo test -p kebab-app -p kebab-cli -j 4 --no-fail-fast → exit 0, 312 passed. (독립 재실행 2회 확인.)
  • smoke(2-문서 ingest): --jsonasset_chunked/asset_timings 출현, human stderr ⏱ parse 3ms · chunk 673ms · expand 0ms · embed 96ms · store 33ms.
  • 별도 opus 코드리뷰 → APPROVE. MEDIUM/LOW 반영: store_ms 경계 정정(stale-vector purge 를 embed phase 로 이동 → store_ms = SQLite put_* 만), 최종 expansion 프레임 중복/0-0 가드.

비범위 / 한계

  • image/pdf 경로는 phase timing 없음(asset_chunked 만 — phase shape 가 OCR/caption 이라 다름).
  • expansion_progress 비-TTY human 은 로그 폭주 방지로 기본 억제(--json 은 전량). 라이브 카운터 rate/ETA 의 실제 체감은 원격 LLM 연결 도그푸딩에서 별도 확인 권장.
  • (후속) cli 통합테스트가 <worktree>/target/debug/kebab 하드코딩 → CARGO_TARGET_DIR 리다이렉트와 충돌. 이 PR 무관(기존 이슈), env!("CARGO_BIN_EXE_kebab") 로 교체 권장.

시험 항목 (Test Plan)

  • clippy -D warnings 0 / test 312 passed (독립 검증)
  • 신규 이벤트 직렬화 kind 판별 + 순서 불변식 테스트
  • smoke: --json 새 kind + human phase 타이밍 라인
  • (도그푸딩) 원격 LLM expansion 켜고 expansion_progress 라이브 카운터 체감 확인

Assisted-by: Claude Code

## 요약 ingest 진행 이벤트가 asset(문서) 단위(`asset_started`/`asset_finished`)뿐이라, 한 문서 내부의 parse / chunk / **expansion(별칭 LLM, 청크당 순차 호출)** / embed / store 가 깜깜했다. expansion 은 청크당 ~1~4s(원격 GPU Ollama)이고 큰 문서는 청크 수백~천 개 → 그 한 문서에서 수십 분이 걸리는데 진행바는 `1/N` 에 멈춘 듯 보여 **사용자가 병목을 못 봤다**. 이 PR 은 asset 내부 phase 를 노출해 어디서 시간이 가는지 즉시 보이게 한다 — 청크 수 · expansion 라이브 카운터 · phase 별 소요시간. wire `ingest_progress.v1` 은 **additive(backward-compat)** 유지. 설계: docs/superpowers/specs/ 없음(진행-로깅 계측, design §2.4a 의 "future embed-batch events" 자리 확장). 동기/벤치 근거는 `tasks/HOTFIXES.md` 2026-06-02 항목. ## 변경 - `IngestEvent` 신규 변이 3개 (`#[serde(tag="kind")]` → wire v1 호환): - `asset_chunked { idx, total, chunks }` — 청킹 직후(expansion/embed 전) 청크 수 즉시 노출. markdown/image/pdf 모두. - `expansion_progress { idx, total, done, chunks }` — expansion 루프 중 **스로틀**(25청크 또는 ≥1s). 캐시 히트도 `done` 포함. 채널 폭주 방지. - `asset_timings { idx, total, parse_ms, chunk_ms, expansion_ms, embed_ms, store_ms }` — markdown 경로 phase 별 소요시간. - `ingest_one_asset`/`_image_asset`/`_pdf_asset` 에 `idx,total` 스레딩 + markdown 경로 phase 타이머. - CLI `progress.rs` 렌더 — `→ N chunks`, `별칭 확장 done/chunks`, `⏱ parse … · store …`. `--json` 자동, `--quiet` 억제. - wire schema doc additive, TUI reducer no-op arm, 버전 0.23.1 → **0.24.0**. ## 검증 - `cargo clippy --workspace --all-targets -j 4 -- -D warnings` → exit 0. - `cargo test -p kebab-app -p kebab-cli -j 4 --no-fail-fast` → exit 0, **312 passed**. (독립 재실행 2회 확인.) - smoke(2-문서 ingest): `--json` 에 `asset_chunked`/`asset_timings` 출현, human stderr `⏱ parse 3ms · chunk 673ms · expand 0ms · embed 96ms · store 33ms`. - 별도 opus 코드리뷰 → APPROVE. MEDIUM/LOW 반영: store_ms 경계 정정(stale-vector purge 를 embed phase 로 이동 → store_ms = SQLite put_* 만), 최종 expansion 프레임 중복/0-0 가드. ## 비범위 / 한계 - image/pdf 경로는 phase timing 없음(`asset_chunked` 만 — phase shape 가 OCR/caption 이라 다름). - `expansion_progress` 비-TTY human 은 로그 폭주 방지로 기본 억제(`--json` 은 전량). 라이브 카운터 rate/ETA 의 실제 체감은 원격 LLM 연결 도그푸딩에서 별도 확인 권장. - (후속) cli 통합테스트가 `<worktree>/target/debug/kebab` 하드코딩 → `CARGO_TARGET_DIR` 리다이렉트와 충돌. 이 PR 무관(기존 이슈), `env!("CARGO_BIN_EXE_kebab")` 로 교체 권장. ## 시험 항목 (Test Plan) - [x] clippy -D warnings 0 / test 312 passed (독립 검증) - [x] 신규 이벤트 직렬화 `kind` 판별 + 순서 불변식 테스트 - [x] smoke: `--json` 새 kind + human phase 타이밍 라인 - [ ] (도그푸딩) 원격 LLM expansion 켜고 `expansion_progress` 라이브 카운터 체감 확인 Assisted-by: Claude Code
altair823 added 4 commits 2026-06-02 14:50:03 +00:00
asset(문서) 단위뿐이던 ingest 진행 이벤트에 문서 내부 phase 가시성을 추가.
큰 문서가 expansion(별칭 LLM, 청크당 순차)으로 수십 분 걸려도 진행바가
1/N 에 멈춘 듯 보이던 문제 해결.

wire ingest_progress.v1 additive (backward-compat):
- asset_chunked {idx,total,chunks} — 청킹 직후, markdown/image/pdf 전 경로
- expansion_progress {idx,total,done,chunks} — expansion 루프 스로틀
  (25청크 또는 1s, 종료 시 done==chunks). 캐시 히트도 done 에 포함
- asset_timings {idx,total,parse_ms,chunk_ms,expansion_ms,embed_ms,store_ms}
  — markdown 경로 phase별 wall-clock

설계: timing 은 kebab_core::IngestItem(wire-stable) 변경을 피해 신규
AssetTimings 이벤트로 ingest_one_asset 가 직접 emit (AssetFinished 무변경).

CLI(progress.rs): 진행바 sub-message(→ N chunks / 별칭 확장 done/chunks) +
asset 종료 시 phase timing 한 줄(fmt_ms). TUI reducer no-op arm.

검증: clippy -D warnings exit 0; cargo test -p kebab-app -p kebab-cli
312 passed/0 failed. ordering-invariant 테스트 재작성 + 신규 직렬화 테스트.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
작업 입력(brief)과 산출 증거(report: 변경/이벤트/exit-code 검증/smoke 샘플/
잔여 리스크). 메인 세션이 PR 정리 시 드롭 가능한 worktree 메타 아티팩트.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- store_ms 에서 stale-vector orphan purge(LanceDB I/O) 제거 → embed/vector phase
  (embed_ms)로 이동. store_ms 가 이제 SQLite put_* 만 의미(진단 정확도; 편집
  재색인 시 920ms 오귀속 제거). purge 는 여전히 unconditional + upsert 이전.
- 최종 expansion_progress 프레임을 done != last_done 로 가드 (throttle 배수 시
  중복 프레임 + chunks==0 시 0/0 프레임 제거).
- schema/HOTFIXES: store_ms/embed_ms 설명 정정 + dangling IMPL_REPORT 참조 제거.

clippy -D warnings 0, test 312 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude-reviewer-01 approved these changes 2026-06-02 14:50:47 +00:00
claude-reviewer-01 left a comment
Member

회차 1 — 독립 opus 코드리뷰 후 MEDIUM/LOW 반영 검토. wire ingest_progress.v1 additive(신규 kind 3개, 기존 필드 무변경, serde tag 보존, TUI reducer no-op arm)로 호환 유지. idx/total 스레딩 off-by-one 없음(AssetStarted 와 동일 값). 리뷰 반영 확인: store_ms 경계 정정(stale-vector purge 를 embed/vector phase 로 이동 → store_ms=SQLite put_* 만, 진단 정확도), 최종 expansion_progress 프레임 done!=last_done 가드(중복/0-0 제거), schema/HOTFIXES dangling ref 정정. clippy -D warnings 0, test 312 passed(독립 재실행). 잔여 actionable 0 — 머지 동의. (한계: image/pdf phase timing 없음, expansion_progress 라이브 카운터 실측은 원격 LLM 도그푸딩에서.)

회차 1 — 독립 opus 코드리뷰 후 MEDIUM/LOW 반영 검토. wire ingest_progress.v1 additive(신규 kind 3개, 기존 필드 무변경, serde tag 보존, TUI reducer no-op arm)로 호환 유지. idx/total 스레딩 off-by-one 없음(AssetStarted 와 동일 값). 리뷰 반영 확인: store_ms 경계 정정(stale-vector purge 를 embed/vector phase 로 이동 → store_ms=SQLite put_* 만, 진단 정확도), 최종 expansion_progress 프레임 done!=last_done 가드(중복/0-0 제거), schema/HOTFIXES dangling ref 정정. clippy -D warnings 0, test 312 passed(독립 재실행). 잔여 actionable 0 — 머지 동의. (한계: image/pdf phase timing 없음, expansion_progress 라이브 카운터 실측은 원격 LLM 도그푸딩에서.)
altair823 merged commit acb4fa6c65 into main 2026-06-02 17:26:50 +00:00
altair823 deleted branch feat/ingest-progress-detail 2026-06-02 17:26:51 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: altair823-org/kebab#201