Files
kebab/docs/release-notes/v0.32.0-draft.md
altair823 34672e82cc chore: PR #223 회차 1 리뷰 반영 — release notes 사실 정정 (unsafe-libyaml / crate count / 줄수)
리뷰어가 잡은 release-doc 사실 오류 정정:
- dep −2 → dep −1: serde_yaml_ng 0.10 도 unsafe-libyaml 0.2.11 을 transitive 로
  의존(Cargo.lock 확인). 제거된 건 archived serde_yaml 하나뿐. "unsafe-libyaml
  까지 제거" 는 거짓 → 4곳(release notes ×2, Cargo.toml, HOTFIXES) 정정.
- crate 24→20 → 22→20: 이 arc(#219–#222)는 #221 에서 2 crate(kebab-embed/llm)만
  제거. 24→22 는 직전 v0.31.0 spine. cumulative 표기는 명시적 주석으로 분리.
- 누적 줄수 약 −3200 → 약 −3400(실측 git diff fd3b4ae..main = 643 ins/4057 del).

코드 변경 없음(release-facing 문서 + 버전 주석). Cargo.toml 파싱 OK.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Mc6W1fgsrbFKTsqA6P8La
2026-06-27 03:22:30 +00:00

6.3 KiB
Raw Permalink Blame History

v0.32.0 — ponytail-audit over-engineering 정리 arc

"1인용 RAG 치고 너무 복잡해졌다"는 문제의식에서 출발한 over-engineering 감사(ponytail-audit) 결과를 네 PR(#219#222)로 정리한 릴리스. 능력(검색·청킹·RAG 품질)은 전부 유지하되 조작 표면·코드 구조·crate 수를 단순화. 이 arc(#219#222) 누적 약 3400줄, crate 22→20, dep 1(serde_yaml 제거 — unsafe-libyaml 은 serde_yaml_ng 도 transitive 로 가져오므로 유지). (참고: 직전 v0.31.0 spine 이 24→22 를 했으므로 v0.31.0 이전 기준 절대 crate 수는 24→20.)

minor bump 트리거는 #219 의 CLI 플래그/config 키 제거(인터페이스 변경) 하나뿐 — 나머지 셋은 출력·동작 byte-identical 이라 자체로는 patch 급. 실엔진 도그푸딩 evidence 는 tasks/HOTFIXES.md 2026-06-27 항목.

1. 죽은 search-cache scaffold 제거 (#219) — minor (인터페이스 변경)

in-process LRU search cache 는 spine 재작성(#214, v0.31.0)에서 이미 삭제됐는데, 그 비계만 코드·CLI·문서에 남아 있었다. 잔존물을 걷어낸다.

  • 변경 사실: kebab search --no-cachekebab search --explain 플래그 제거(둘 다 이미 no-op/미배선이었음). [rag] explain_default config 키 제거. 내부적으로 App::search/search_uncached 붕괴 + search_uncached_with_config facade 삭제.
  • trade-off: kebab search --no-cache/--explain 를 타이핑하던 muscle memory 가 있으면 "unexpected argument" 에러가 난다. (실제로 둘 다 아무 동작도 안 하던 죽은 플래그였다.) kebab ask --explain그대로 live — 영향 없음.
  • mitigation: search 의 ranking 디테일이 필요하면 kebab search --trace(live)가 pre-fusion lexical/vector/RRF 후보 + per-stage timing 을 보여준다. [rag] explain_default 가 든 옛 config.toml 은 그대로 로드된다(serde 가 unknown 키 무시 — 마이그레이션 불필요).
  • upgrade: 자동. 새 바이너리부터 두 플래그가 사라진다. search_cache: false wire capability(schema.v1)는 정직하게 유지(없는 캐시를 false 로 보고).

2. 9개 동일 code AST chunker → CodeAstV1Chunker 통합 (#220) — 출력 byte-identical

code_{c,cpp,go,java,js,kotlin,python,rust,ts}_ast_v1.rs 9개는 struct 이름 + VERSION_LABEL 문자열만 다른 byte-identical 복붙이었다(chunker 는 tree-sitter 미사용, langSourceSpan::Code 데이터에서 흐름). 단일 CodeAstV1Chunker { version_label } + for_lang(lang) 로 통합(3030줄).

  • 변경 사실: 9개 src 파일 → 1개. for_lang 이 9개 언어를 기존 VERSION_LABEL 문자열로 verbatim 매핑(rust→code-rust-ast-v1, typescript→code-ts-ast-v1 등).
  • trade-off: 없음 — chunker_version 문자열이 언어별로 동일하게 보존돼 chunk_id(= id_for_chunk(doc, chunker_version, …))가 byte-identical → 재인덱싱 0, 임베딩 드리프트 0.
  • mitigation: 9개 골든 스냅샷 테스트가 expected 무수정 통과(단위 증명) + 실코퍼스 A/B 도그푸딩: pre-arc(9-chunker) vs post-arc(consolidated) 바이너리로 같은 코드 코퍼스 ingest → 120 chunks 동일, chunk_id+chunker_version diff 완전 비어있음.
  • upgrade: 자동. 재인덱싱 불필요(같은 chunk_id 라 idempotent upsert 가 no-op).

3. 빈 re-export shim crate 흡수 (#221) — 동작 불변 (crate 22→20)

kebab-embed/kebab-llm 은 "새 type 없음"을 자처한 순수 re-export 셸이었다(trait 은 이미 kebab-core 소유, mock + test helper 만 보유). kebab-core 의 default-OFF mock feature 로 흡수.

  • 변경 사실: 두 crate 삭제, MockEmbedder/MockLanguageModel/assert_* helper 를 kebab-core 로 이동(mock feature, dev-dep 에서만 활성). workspace crate 22 → 20.
  • trade-off: 없음 — production 빌드는 mock 모듈을 컴파일하지 않음(default-OFF). trait surface·동작 불변. 외부 integration 영향 0(단일 바이너리).
  • mitigation: mock byte-identical(import rewrite 만), 의존 crate 테스트 전부 녹색.
  • upgrade: 자동. 사용자 표면 무변경.

4. FusionPolicy inline + dual-YAML 통일 + NLI default 제거 (#222) — 출력 불변

audit 잔여 작은 정리 셋. (1) 변종 하나뿐이던 FusionPolicy::Rrf enum 을 HybridRetriever.k_rrf: u32 로 inline(RRF 수식 byte-identical). (2) serde_yaml(0.9, archived) → serde_yaml_ng(0.10, maintained fork) 일원화 — 중복 YAML dep(serde_yaml) 제거(workspace pin). (unsafe-libyaml 은 serde_yaml_ng 도 transitive 로 의존하므로 트리에 유지 — 제거된 건 archived serde_yaml 하나.) (3) NliVerifier::hypothesis_token_countOk(0) default 제거(prod 가 이미 override 라 동작 불변, footgun 을 compile-time 보장으로).

  • trade-off: 없음 — 검색 순위·YAML 파싱·prod NLI 동작 전부 불변.
  • upgrade: 자동.

버전

0.31.0 → 0.32.0 (minor). 새 기능·새 CLI 명령은 없으나 #219 의 플래그·config 키 제거가 인터페이스 변경이라 minor 강제. 나머지 셋은 byte-identical 정리.

도그푸딩 (실엔진 종단 검증, 2026-06-27)

  • chunker A/B (핵심): pre-arc(v0.31.0, 9-chunker) vs post-arc(consolidated) 바이너리로 5언어 9파일 코드 코퍼스 ingest. 양쪽 120 chunks, chunk_id + chunker_version diff 완전 비어있음 → consolidation 이 실코퍼스에서 byte-identical 임을 종단 확증. 라벨: code-c/go/python/rust/ts-ast-v1.
  • GPU: r9700 ollama 스왑(lemonade↔ollama-r9700), snowflake-arctic-embed2 임베딩으로 ingest 성공, lexical 검색(split oversize → 해당 함수 청크 hit) 정상. lemonade 무조건 복구 확인.
  • CLI 표면: search --no-cache/--explain → "unexpected argument" 에러(제거 확인), ask --explain/search --trace → help 에 present(live 확인).

알려진 한계 / 후속

  • RAG 생성(ask) 경로는 이 arc 가 변경하지 않아(PR4 NLI 는 prod override 라 불변) GPU LLM ask 재도그푸딩은 생략(GPU 는 임베딩 ingest 로 행사). 다음 RAG-prompt/모델 변경 시 재개.
  • kebab eval 은 게이팅하지 않고 일급 subcommand 유지(audit 의 "placeholder" 전제는 stale 주석 오독 — 실제 완전 배선됨). stale 주석만 정정.