Files
kebab/docs/release-notes/v0.20.1-draft.md
altair823 028d9ad4ea docs(release): v0.20.1 release notes draft + spec/plan dogfood cross-link
#1 (사용자 요청): release notes draft 작성 + spec/plan 의 dogfood
evidence cross-link 보강.

docs/release-notes/v0.20.1-draft.md (신규):
- 4 단락 본문 (한국어 2자 query 지원 + 영어 substring 회귀 + V007→V009
  자동 backfill + ingest 성능 영향).
- Migration cascade table (lexical_index_version, corpus_revision,
  wire schema shape preservation).
- API + dependency 변경 (lindera v3, lindera-ko-dic v3, retired
  short_query_hint helper, 새 facade APIs).
- Breaking changes 명시 (영어 substring 회귀, 첫 부팅 latency, DB/
  binary 크기 증가).
- Upgrade 절차 + Known limitation + 14 dogfood scenario reference.

spec Appendix B (segmentation evidence):
- "Empirical verification (2026-05-28 dogfood — post-merge update)"
  subsection 신규. prior-knowledge 가정 vs 실측 결과 table. Scenario
  1-4 모두 verified 표시. ko-dic 의 '서울특별시' → '[서울, 특별시]'
  분해 증거 명시.

plan Changelog:
- post-implementation entry: 22 commit on branch, S3 blockers, S7
  cascade, S11 sanity regression updates, opus PR review 4 finding
  fixes.
- dogfood evidence entry: 14 scenario verify pass, ko-dic 분해
  evidence, HOTFIXES + spec Appendix B cross-link.

Spec: …spec…md Appendix B
Plan: …plan…md (post-implementation + dogfood evidence Changelog)
Release notes: docs/release-notes/v0.20.1-draft.md
2026-05-28 13:34:33 +00:00

8.8 KiB

title, created, status, release_trigger
title created status release_trigger
kebab v0.20.1 release notes (draft) 2026-05-28 draft
사용자 도그푸딩 필요 (Bug
frozen design contract 변경 (design §5.5 chunks_fts
trigram → unicode61 + 형태소 column)

kebab v0.20.1 — 한국어 형태소 검색 + 영어 substring 회귀

v0.20.0 (sub-item 1 scanned PDF OCR via qwen2.5vl:3b, 2026-05-27) 후속의 patch release. v0.20.x 라인의 두 누적 enhancement (logging round 2 + 한국어 morphological tokenizer) 를 하나로 묶어 cut.

핵심 변경

1. 한국어 2자 query 지원 — Bug #8 해소

이전 V007 (v0.17.0+) 의 trigram FTS5 tokenizer 는 3-character gram 최소 인덱싱이라 '한국' / '서울' / '지하철' 같은 1-3자 한국어 단어 query 가 종종 0-hit 였습니다. 사용자 도그푸딩 round 3/4 의 가장 큰 search experience surface.

v0.20.1 의 해결책chunks_fts tokenizer 를 unicode61 로 환원 + lindera ko-dic 형태소 분석기로 한국어 chunk text 를 분해해 별 column tokenized_korean_text 에 pre-fill. FTS5 trigger 의 CASE expression 이 raw text 앞에 prepend 해 단일 query 로 두 column 모두 매칭.

# v0.17.0 (V007 trigram): 0 hit
# v0.20.1 (V009 morphological): hit (chunk 의 ko-dic 분해 결과에 '한국' morpheme 가 존재)
kebab search '한국'
kebab search '서울'

Dogfood evidence (tasks/HOTFIXES.md 2026-05-28 entry + docs/DOGFOOD.md §2.1bis 의 reference fixture 14 scenario):

Query v0.17.0 (V007 trigram) v0.20.1 (V009)
'한국' 2자 0 hit hit
'서울' 2자 0 hit hit
'지하철' 3자 substring (제한적) morpheme + raw token 모두 매칭
'서울특별시' compound substring ko-dic 분해 [서울, 특별시]

Known limitation: ko-dic 가 compound noun (예: 한국정부) 을 단일 token 으로 저장하는 경우 그 chunk 의 '한국' 단독 query 는 hit X. KB 가 영어/code 위주면 한국어 token 자체 부재로 lexical 0-hit 자연. N-gram supplement (sub-token 추가 emit) 는 v0.21.x P9 follow-up.

2. 영어 substring 매칭 회귀 (V002 동작 환원)

V007 trigram 의 ad-hoc 부산물이었던 영어 substring 매칭 ('token' query 가 'tokenizer' chunk 도 hit) 은 V009 의 unicode61 transition 으로 사라집니다. V002 (pre-v0.17.0) 의 whole-token 매칭으로 환원.

# v0.17.0: 'token' query → 'tokenizer' chunk hit (substring recall ↑, 단어 경계 정밀도 ↓)
# v0.20.1: 'token' query → 'token' 토큰만 hit, 'tokenizer' 는 다른 token
kebab search --mode lexical 'token'      # 다른 결과 가능
kebab search --mode lexical 'tokenizer'  # 정확한 token 매칭

substring recall 이 필요한 시나리오는 vector 또는 hybrid mode 권장 (RRF 가 lexical + semantic 결합). spec §3 Non-Goals Path A 의 설계 결정 — lexical 의 단어 경계 정밀도 vs substring recall trade-off 에서 후자 포기.

3. V007 → V009 자동 backfill (재-ingest 불필요)

기존 V007 KB 를 v0.20.1 binary 로 첫 부팅할 때 App::open_with_config 의 first-boot hook 이 자동 실행:

  1. V009 migration apply (schema 변경: tokenized_korean_text TEXT column ADD + chunks_fts re-create with unicode61 + CASE expression triggers).
  2. backfill_tokenized_korean_text API 호출 — chunks 의 NULL tokenized_korean_text row 를 lindera 로 분해 후 UPDATE. 1000-row batch transaction + progress callback.
  3. chunks_au trigger 가 chunks_fts 를 자동 재-index.

KB 크기 비례 latency:

  • 1만 chunk → ~30-60초 (lindera tokenize + UPDATE + trigger overhead).
  • 10만 chunk → ~5-10분.
  • stderr 의 tracing::info! progress log (korean tokenizer backfill: 500/10000) 발화. 사용자 hang 인지 방지.
  • 부분 완료 (Ctrl-C) 후 재실행 시 IS NULL filter 로 idempotent 이어 처리.

backfill 실패 시 (예: lindera dict load fail) App::open_with_config 은 success 반환 + warn log. vector/hybrid mode 정상 사용 가능.

4. Ingest 성능 영향

새 chunk ingest 시 chunker (kebab-chunk::md_heading_v1, code_*_ast_v1, pdf_page_v1, tier2_shared) 가 chunk emit 직전에 tokenize_korean_morphological(text) 호출. OnceLock 캐시로 dictionary load 가 process-lifetime 동안 1회 — amortized cost 낮음.

도그푸딩 측정 (1781 markdown / 9050 chunk):

  • v0.20.0 ingest baseline: ~700초.
  • v0.20.1 ingest: ~671초 (실측 — overhead 거의 무의미, chunk text 길이 비례 +5-10% 예상).

kebab.sqlite 파일 크기 영향:

  • tokenized_korean_text column 추가 (한국어 chunk 비례 +20-30% column data).
  • chunks_fts shadow 의 indexed text 가 raw + tokenized 합 (Korean-heavy KB 에서 ~2배 chunks_fts 크기).
  • 영어/code 위주 KB 에서는 tokenized_korean_text 가 NULL 또는 short → 영향 minimal.

binary 크기:

  • v0.20.0: ~270 MB (release).
  • v0.20.1: ~390 MB (lindera-ko-dic embedded dict 의 ~120 MB 추가).

Migration cascade

Version field v0.20.0 v0.20.1
lexical_index_version lex:{chunker} lex:{chunker}:fts5-v009-korean-morphological
corpus_revision V004 seed = 0 V009 migration tail 의 +1 (post-migration baseline = 1)
chunker_version unchanged unchanged
parser_version unchanged unchanged
embedding_version unchanged unchanged
Wire schema (search_response.v1, answer.v1) shape unchanged shape unchanged (hit ordering / snippet content 만 변화)

eval runner 의 config_snapshot_json 가 자동으로 lexical_index_version 의 V009 suffix 를 picks up — crates/kebab-eval/tests/fixtures/eval/run-1.json 의 V009 baseline 으로 regenerate 됨.

API + dependency 변경

신규 workspace dependencies:

  • lindera = "3" (MIT/Apache-2.0)
  • lindera-ko-dic = "3" (Apache-2.0, MeCab-ko-dic upstream)

신규 facade-level API (kebab-app*_with_config 패턴 따라):

  • kebab_chunk::tokenize_korean_morphological(text: &str) -> Option<String>
  • kebab_store_sqlite::SqliteStore::backfill_tokenized_korean_text<F, T>(progress, tokenize) -> Result<u64>

retired:

  • kebab_app::short_query_hint() helper — V007 시절 advisory. V009 의 2-char Korean query hit 으로 obsolete. SearchResponse.hint struct field + wire schema hint field 는 forward-compat 차원에서 보존 (항상 None).

Logging round 2 (v0.20.x sub-item 1 후속, PR #190 머지)

  • PDF OCR raster image dimension capture (PR #189 의 round 1 null 결함 fix).
  • V008 SQLite mirror — historical OCR query table.
  • CLI kebab inspect ocr-stats + kebab inspect ocr-failures.
  • Log retention policy — keep_recent_runs + retention_days.

자세한 내용 = HANDOFF.md "v0.20.x ingest log r2" entry + spec docs/superpowers/specs/2026-05-28-v0.20.x-logging-r2-spec.md.

Breaking changes / 사용자 영향

  • 영어 lexical 의 substring 매칭이 사라짐 — 사용자가 'token' query 로 'tokenizer' 도 찾는 패턴 의존 시 vector/hybrid mode 로 mode-switch 권장. release notes 만 보고 mode 변경 안 한 사용자는 자기 KB 의 검색 결과 변화 인지.
  • 첫 부팅 latency — 큰 KB 의 사용자는 v0.20.1 binary 의 첫 호출이 30초~10분 hang. stderr progress log 확인.
  • DB / binary 크기 증가kebab.sqlite +20-30% (Korean-heavy), binary +120MB (lindera ko-dic embedded). /build/cache/tmp 또는 별 디스크에 KB 둔 사용자는 영향 minimal.

Upgrade 절차

# 1. binary 교체 (release tag v0.20.1)
git fetch && git checkout v0.20.1 && cargo build --release -p kebab-cli

# 2. 첫 호출 — V009 migration + eager backfill 자동
kebab search '한국'   # stderr 의 backfill progress log 확인

# 3. 새 검색 패턴 확인
kebab search '서울'   # 2자 query hit
kebab search 'tokenizer'   # whole-token (substring recall 회귀)

회귀 발견 시 tasks/HOTFIXES.md 또는 GitHub issue 보고.

References