refactor: 척추 재작성 — 표면·동작·내부 단순화 (cuts + config 재편 + ingest 스파인) #214

Merged
altair823 merged 29 commits from refactor/spine-cuts into main 2026-06-24 15:59:08 +00:00

29 Commits

Author SHA1 Message Date
cebfc893ad refactor: 제거 기능 stale surface 정리 — 세션/wire 필드/rag_multi_turn/crate수 (PR #214 회차 1)
cut 으로 제거된 기능이 diff 밖 contract surface 에 남긴 잔재 정리:
- integrations/claude-code/kebab/SKILL.md: 제거된 --session/session_id 안내,
  answer.v1 의 conversation_id/turn_index 필드 목록, rag-v2 기본 pin, kebab tui
  언급 제거. 기본 템플릿 rag-v4(대체 rag-v3)로 갱신.
- docs/mcp-usage.md: ask 입력 스키마의 session_id, 'Session 관리(multi-turn)'
  섹션 전체(chat_sessions/chat_turns 포함), 예시의 conversation_id/turn_index 제거.
- docs/wire-schema/v1/answer.schema.json + answer_event.schema.json: Answer 가
  더는 방출 않는 conversation_id/turn_index 속성 제거(producer/doc 괴리 해소).
- schema.rs + wire.rs: capabilities.rag_multi_turn true→false(search_cache 와
  동일 처리; frozen v1 맵이라 키는 유지, 값만 flip).
- CLAUDE.md: 24→22 crates(tui+candle crate 제거 반영).
2026-06-24 15:53:50 +00:00
0ae739eeaf fix(config): v4→v5 마이그레이션이 image-only Option OCR 키를 pdf 로 누출 (PR #214 회차 1)
endpoint/det_model/rec_model/dict 는 default None 이라 reconcile 가 pdf 블록에
채우지 않는다(None 은 annotated-default 에서 누락). image 만 설정한 이 키를 공유
[ingest.ocr] 로 끌어올리면 resolve_ocr overlay 가 (medium_has(pdf,key)=false 라)
pdf 로 누출돼, pdf OCR endpoint/asset 경로가 v4 와 달라지고 det/rec/dict 는
ingest_config_signature 에 들어가 강제 재색인까지 유발했다. step_4_to_5 에서
Option 키는 pdf 도 명시한 경우에만 hoist 하도록 OPTION_OCR_KEYS 가드 추가.

기존 round-trip 테스트는 before=Config::from_file(v4) 가 이미 마이그레이션+resolve
를 거친 오염값이라 after==before tautology 였음 — pdf.det_model==None 명시 검증
추가 + 비대칭 image-only-endpoint 회귀 테스트 신설.
2026-06-24 15:46:20 +00:00
54d361637b docs(hotfix): Phase 3 module split 기록 (lib.rs 4331→493) 2026-06-24 14:24:01 +00:00
00ead29720 refactor(app): ingest 코드를 src/ingest 모듈로 분리 — lib.rs 4331→493줄, API 무변, 재인덱싱 게이트 IDENTICAL 2026-06-24 14:23:32 +00:00
26bc095418 docs(hotfix): spine Phase 3 — ingest stage 추출(API 6→2 + store/fingerprint/extract/chunk), 전부 재인덱싱 게이트 IDENTICAL 2026-06-24 13:59:56 +00:00
2a0a30aa1c refactor(app): chunk_asset stage 헬퍼 — 청커 선택+tier3 fallback 통합 2026-06-24 13:57:17 +00:00
2bbe2f8ace refactor(app): markdown을 extractor registry 경유로 통일 (extract stage 대칭화)
markdown ingest arm 이 그동안 유일하게 `App::extract_for` extractor
registry 를 우회하고 `kebab_parse_md::{parse_frontmatter, parse_blocks,
build_canonical_document}` free function 을 직접 호출했다 ("the single
biggest asymmetry"). 이를 image/pdf/code 와 동일하게 registry 경유로
통일.

- `kebab-parse-md` 에 `MarkdownExtractor` 신설 — 기존 free function 3종을
  동일 순서·동일 인자로 감싸 `bytes → CanonicalDocument` 생산만 담당.
  fm_span_end / count_lines_in / build_body_hints 헬퍼도 함께 이식.
- `App.extractors` registry 에 등록 (11 → 12 entry), markdown 이 `supports`
  로 발견되도록 첫 entry 로 배치.
- `ExtractContext` 에 `source_id` / `source_trust` 필드 추가 — markdown
  frontmatter 가 per-source trust 기본값을 override 하고 그 precedence 가
  `parse_frontmatter` *내부*에서 결정되므로 ctx 가 carry 해야 함. 다른
  extractor 는 None (post-extract 에서 source_id stamp 유지).
- 핸들러는 추출 stage 만 registry 로 이전 — version stamping / chunking /
  embedding / store 는 그대로. IngestItem.warnings 는 pdf/code 처럼
  `canonical.provenance` 의 Warning 이벤트에서 도출.

byte-identical 검증: parity gate-ingest (all-markdown 183 doc / 7676 chunk)
CHUNKS / SEARCH / ASK 모두 IDENTICAL. clippy 0, kebab-app + kebab-parse-md
test 전체 green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Mc6W1fgsrbFKTsqA6P8La
2026-06-24 13:30:54 +00:00
9f40c88722 refactor(app): fingerprint_and_skip — effective version+skip 결정 중앙화 (4× 복제 제거) 2026-06-24 13:06:42 +00:00
0f9a76997d refactor(app): ingest store 시퀀스를 store_asset 헬퍼로 추출 (4× 중복 제거) 2026-06-24 12:49:09 +00:00
d501ce2626 refactor(app): ingest API 6변종 → 2 (ingest + ingest_with_config{IngestOpts})
summary_only를 IngestOpts에 흡수, progress/cancellable/opts 변종 제거.
재인덱싱 게이트 CHUNKS/SEARCH/ASK byte-IDENTICAL, clippy --all-targets 0.
2026-06-24 12:36:20 +00:00
d24f9641d5 docs(plan): Phase 3 ingest — API 6→2 + 중앙 chunker_for + fingerprint 중앙화 (+ full pipeline 위험-게이트) 2026-06-24 12:18:11 +00:00
38990b4d44 docs(hotfix): spine Phase 2 — config 슬라이스 + 표면 정리 완료 (OCR통합 v5 + env 75→22 + consumer 슬라이스) 2026-06-24 12:00:24 +00:00
2dfbbe4f43 refactor(config): consumer들이 &Config 대신 타입 슬라이스 수령 (god-struct 결합 해소) 2026-06-24 11:55:10 +00:00
bf7769cf5a refactor(config): env 97→~25 + 노출 키 109→~30 (표면 정리)
apply_env 의 KEBAB_* 매치 암을 103개→22개로 정리. 삭제된 암은 런타임에서
바꿀 일이 거의 없는 per-field 튜닝 노브(score_thresh, rrf_k, temperature,
multi_hop_*, nli_threshold, chunker_version, context_tokens 등) — struct
field 와 serde default 는 그대로 유지하므로 TOML 로는 여전히 설정 가능.

유지한 22개: endpoint×3, 모델명/프로바이더×5, 경로×2, 병렬도×2,
청킹 target/overlap×2, OCR 엔진/모델/언어+per-medium enabled×5,
caption enabled×1, search default_k×1, rag prompt_template_version×1.

영향 범위: struct field 삭제 없음(defaults 불변) → search/ask/chunk 출력
byte-identical 확인 (parity gate u2-surface IDENTICAL ✓).

docs: README KEBAB_* 항목을 실제 노출 키 목록으로 교체.
      SMOKE.md config 예시를 ~30개 공통 키로 슬림화 + env 설명 갱신.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Mc6W1fgsrbFKTsqA6P8La
2026-06-24 11:21:11 +00:00
da323af87b refactor(config): OCR 중복 제거 — 공유 [ingest.ocr] 엔진 블록 + v4→v5 마이그레이션
Phase 2 Unit 1. OcrCfg(image) 13필드가 PdfOcrCfg(pdf) 와 전부 중복(image 고유
0, pdf 고유 4) + apply_env 에 KEBAB_IMAGE_OCR_*/KEBAB_PDF_OCR_* 27 arm 복제를
제거한다.

- 신규 SharedOcrEngineCfg(13 공유 필드, 전부 Option, default None) = [ingest.ocr].
  엔진 설정 단일 출처. image/pdf 블록은 on/off 토글 + override.
- load-time resolution(Config::resolve_ocr, from_file 호출): 공유 필드가 Some 이고
  미디어 블록이 그 키 미명시면 concrete OcrCfg/PdfOcrCfg 로 overlay(presence 는
  toml::Value 로 판정; 미디어 > 공유 > 내장 default). struct 필드는 그대로 두고
  엔진 필드에 #[serde(default)] 만 추가(slim 블록 파싱) → image(gemma4:e4b/1600)
  vs pdf(qwen2.5vl:3b/2048) 미디어별 기본값 보존.
- resolver Config::image_ocr()/pdf_ocr() 추가. consumer(kebab-parse-image,
  kebab-app build_*_ocr_engine·ingest gate·pdf_ocr_apply·ingest_config_signature)가
  전부 경유 → god-struct 직접 read 제거.
- apply_env: 27 arm → 공유 KEBAB_OCR_* 12 arm(image+pdf 동시) + pdf 고유 4 arm +
  미디어별 KEBAB_IMAGE_OCR_ENABLED/KEBAB_PDF_OCR_ENABLED.
- step_4_to_5: [ingest.image.ocr] 12 엔진 키를 [ingest.ocr] 로 move_table(enabled
  제외). pdf 블록 무손상(reconcile 이 채워 공유 overlay 오염 X). annotated_default
  도 동일 통합으로 v5 canonical 형상. CURRENT_SCHEMA_VERSION=5.
- v4→v5 round-trip 테스트(비-default image engine 보존 + pdf 오염 X + 멱등). effective
  OCR 바이트 동일 → ingest_config_signature 불변 → 강제 재색인 없음.

검증: clippy --workspace --all-targets 0 / kebab-config·kebab-parse-image·
kebab-parse-pdf·kebab-app 테스트 pass. surface: README [ingest.ocr] 절 + SMOKE
config 블록 + DOGFOOD env + HOTFIXES dated entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Mc6W1fgsrbFKTsqA6P8La
2026-06-24 11:03:39 +00:00
c9a9832f7f docs(plan): Phase 2 config — OCR 통합 + 표면 정리 + slice refactor (3 유닛 순차) 2026-06-24 10:33:27 +00:00
f54e97d2dd docs(hotfix): spine Phase 1 — 5건 삭제 완료, 코어 출력 byte-identical 검증 2026-06-24 10:22:46 +00:00
0af9d58c95 test: 삭제된 심볼 참조 정리 (session_id, rag-v1→v4, cache_capacity) — worker cargo check가 test 타깃 미컴파일로 누락 2026-06-24 10:11:13 +00:00
4314e503c2 chore: Cargo.lock 갱신 — kebab-tui + kebab-embed-candle 제거 반영 2026-06-24 10:06:26 +00:00
3c3dcc86cd refactor: kebab-tui crate + tui 서브커맨드 제거 (UI=CLI/MCP) 2026-06-24 09:59:54 +00:00
040d17f122 refactor(embed): candle provider/crate 제거 — fastembed+ollama로 충분
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Mc6W1fgsrbFKTsqA6P8La
2026-06-24 09:59:13 +00:00
1d32aa645a refactor: multi-turn 세션 제거 (ask --session, chat_sessions/turns) + V015 drop migration 2026-06-24 09:57:12 +00:00
470e94bb2d refactor(app): search LRU 캐시 제거 (p9-fb-19) — 동작 불변, 표면 축소
- App::search() → search_uncached() 직통 (캐시 로직 전체 삭제)
- SearchCacheKey struct + impl 제거
- App.search_cache 필드 + 초기화 블록 제거
- build_cache_key() / clear_search_cache() 제거
- config SearchCfg.cache_capacity + default_cache_capacity() 제거
- CLI clear_search_cache() 호출 제거; --no-cache 플래그는 유지(no-op)
- wire/schema search_cache 값 true → false (필드 유지)
- lru workspace dep + kebab-app direct dep 제거
- unicode-normalization dep 유지 (first_question_title() 에서 사용 중)
2026-06-24 09:48:54 +00:00
7c935c6b96 refactor(rag): legacy 템플릿 rag-v1/v2 제거 — v3/v4만 유지 2026-06-24 09:45:17 +00:00
e1edb9224b docs: Task 0 parity baseline 동결 + gate를 python3/실측 경로로 수정 (output-equality 검증됨) 2026-06-24 09:00:38 +00:00
b04b865c73 docs(plan): Parity Gate를 출력-동등성 diff로 + Task 0 재현 KB 구축으로 수정
eval golden set이 ground-truth 라벨 없음 + 도그푸딩 KB 임베더 down → 라벨 기반
metric 패리티 불가. 삭제 단계엔 출력 동등성(search/ask --json byte-diff + chunk diff)이
더 정확하고 라벨·외부엔드포인트 비의존. Task 0는 kebab 자체 docs + fastembed 로컬 +
lemonade RAG로 작은 재현 KB 구축 후 baseline 출력 동결.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Mc6W1fgsrbFKTsqA6P8La
2026-06-24 07:30:56 +00:00
967e10cfc1 docs(plan): 척추 단순화 Phase 0(baseline) + Phase 1(cuts) 구현 계획
Phase 0: 코어 품질 baseline 동결(kebab eval run + chunk dump). Phase 1: 5건 순수
삭제(search 캐시 → RAG v1/v2 → candle → 세션+V015 → TUI), 각 PR 마다 Parity Gate
(eval compare 델타≈0 + chunk byte-diff=0) HARD GATE. 정확한 제거점(파일:심볼) 명시.
ingest API 5→1 통합은 Phase 3(ingest 스파인)로 이동. Phase 2~5는 도달 시 상세 작성.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Mc6W1fgsrbFKTsqA6P8La
2026-06-24 07:07:59 +00:00
6dbbbb47fb docs(spec): 코어 도그푸딩 품질 패리티 게이트 추가 (per 수정 단위 HARD GATE)
사용자 필수 제약 반영: 각 수정 단위(PR/phase)마다 코어 기능(md ingest·검색·
single-hop RAG+citation)의 도그푸딩 품질이 직전 baseline 과 반드시 비슷해야 하며
회귀 시 머지 금지. baseline 동결 → per-unit `kebab eval compare` + ingest 출력
byte-diff=0 게이트. 이 게이트가 PR 분할 경계와 완료 정의를 지배.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Mc6W1fgsrbFKTsqA6P8La
2026-06-24 06:58:45 +00:00
911055ef54 docs(spec): 척추 재작성 / 단순화 설계 — spine rewrite + simplification
기능 추가로 산만해진 표면·동작·내부를 강하게 단순화하는 설계. 단일 사용자·pre-1.0
이점으로 능력은 (거의) 유지하되 조작 표면·코드 구조를 절반 이하로.

핵심:
- Cuts: TUI, multi-turn 세션, legacy RAG v1/v2, search LRU 캐시, candle 임베더,
  ingest API 5변종→1 (crate 24→22).
- 스파인 4 crate 재작성: config god-struct→타입 슬라이스, ingest 4193줄 모놀리스→
  stage 파이프라인, chunk 중앙 selector, rag 2633줄→합성 stage(순수 query→Answer).
- 표면: config 109→~30, env 97→~25, search 20플래그→~6(--filter).
- 불변식: ingest 출력 byte-identical(재색인 없음) + wire 출력 계약 불변(MCP/스킬 무영향).

brainstorming 7개 결정 기록. frozen contract 부분 supersede.

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