feat(config): config.toml v2→v3 스키마 재편 — 미디어 [ingest.*] 통합 + 무손실 자동 마이그레이션 #207

Merged
altair823 merged 12 commits from feat/config-schema-reorg into main 2026-06-04 14:36:44 +00:00
Owner

요약

config.toml 의 옵션이 누적되며 생긴 군더더기(미디어 설정 산재, OCR 중복·비대칭, init 60+ 필드)를 정리한다. 미디어 형식 설정을 [ingest.*] 우산 아래로 통합하고, 기존 v2 파일을 무손실 자동 마이그레이션하며, 각 옵션에 인라인 설명 주석을 부착한다.

레이아웃: [indexing][ingest](스칼라), [chunking][ingest.chunking], [image.ocr]/[image.caption][ingest.image.*], [pdf.ocr][ingest.pdf.ocr](+ paddle 경로 대칭 추가로 v2 의 "pdf 가 image paddle 을 빌려쓰던" 비대칭 제거).

설계: docs/superpowers/specs/2026-06-04-config-schema-reorg-design.md
계획: docs/superpowers/plans/2026-06-04-config-schema-reorg.md

깨지지 않도록 고정한 3가지 불변식

  • signature 바이트 불변ingest_config_signature 출력이 값 기반이라 struct 경로 재편과 무관하게 동일 → 업그레이드 시 재색인 0 (ingest_signature_image_paddle_byte_stable 골든 + 도그푸딩 실증).
  • env 이름 100% 보존apply_env whitelist 의 키 문자열(LHS) 불변, 대입 대상(RHS)만 새 경로. 기존 KEBAB_* 스크립트 무파손. 신규 KEBAB_PDF_OCR_{DET_MODEL,REC_MODEL,DICT,SCORE_THRESH,UNCLIP_RATIO,MAX_BOXES} 추가.
  • load 시 메모리 내 자동 변환 — v3 는 최초의 non-additive rename 이라 미변환 v2 파일이 serde default 로 떨어지면 설정 유실. Config::from_fileschema_version < 3 파일을 디스크 미변경으로 메모리에서 변환해 유실 0. 파일 갱신은 여전히 kebab config migrate.

변경 카테고리

  • kebab-config: Config/IngestCfg 재배치(leaf 구조체 불변), PdfOcrCfg paddle 대칭 6키, ser_f32_clean(f32 직렬화 찌꺼기 제거), apply_env RHS 갱신, from_file 자동 변환, migrate::step_2_to_3(테이블 relocation + paddle 값 복사 + 멱등), key_comment(per-option 주석).
  • kebab-app / kebab-eval / kebab-parse-image: config.*config.ingest.* call-site sweep + ocr_engine_version_for_sig 미디어화.
  • 문서: README Configuration([ingest.*] + migrate 안내), docs/SMOKE.md config 예시(v3), HOTFIXES dated entry, 선행 마이그레이션 spec 교차링크. workspace version 0.27.0→0.28.0(minor).

검증

  • cargo clippy --workspace --all-targets -j 8 -- -D warnings → 0 warnings (리더 독립 재실행 EXIT=0).
  • cargo test -p kebab-config -p kebab-app -p kebab-eval -j 8 → 전부 test result: ok, FAILED 0 (리더 독립 재실행 EXIT=0). ignored 소수는 라이브 Ollama 의존 기존 테스트로 본 변경 무관.
  • 무손실 골든(tests/migrate_v3.rs): 사용자 실제 v2 config 의 값·주석·대안 줄 보존 + v3 파싱 일치 + 멱등.
  • 경계 케이스 직접 검증: [ingest.code]로 implicit [ingest]가 이미 있는 상태 + 비기본 [indexing](7/3/true) relocation → 스칼라가 sub-table 헤더 앞에 올바르게 직렬화, 값 전부 보존, 유효 TOML.
  • 도그푸딩: release 빌드로 사용자 실제 config kebab config migrate(11 changes, .bak 백업, 멱등) + 재색인 0 실증(v2 자동변환·v3 디스크 양 경로 모두 unchanged).

시험 항목 (Test Plan)

  • 기존 KEBAB_CHUNKING_* / KEBAB_IMAGE_OCR_* env 가 새 경로로 정상 반영
  • v2 config 로 kebab ingest → 재색인 0
  • kebab config migrate 멱등

Assisted-by: Claude Code

## 요약 config.toml 의 옵션이 누적되며 생긴 군더더기(미디어 설정 산재, OCR 중복·비대칭, init 60+ 필드)를 정리한다. 미디어 형식 설정을 `[ingest.*]` 우산 아래로 통합하고, 기존 v2 파일을 **무손실 자동 마이그레이션**하며, 각 옵션에 인라인 설명 주석을 부착한다. 레이아웃: `[indexing]`→`[ingest]`(스칼라), `[chunking]`→`[ingest.chunking]`, `[image.ocr]`/`[image.caption]`→`[ingest.image.*]`, `[pdf.ocr]`→`[ingest.pdf.ocr]`(+ paddle 경로 대칭 추가로 v2 의 "pdf 가 image paddle 을 빌려쓰던" 비대칭 제거). 설계: docs/superpowers/specs/2026-06-04-config-schema-reorg-design.md 계획: docs/superpowers/plans/2026-06-04-config-schema-reorg.md ## 깨지지 않도록 고정한 3가지 불변식 - **signature 바이트 불변** — `ingest_config_signature` 출력이 값 기반이라 struct 경로 재편과 무관하게 동일 → 업그레이드 시 재색인 0 (`ingest_signature_image_paddle_byte_stable` 골든 + 도그푸딩 실증). - **env 이름 100% 보존** — `apply_env` whitelist 의 키 문자열(LHS) 불변, 대입 대상(RHS)만 새 경로. 기존 `KEBAB_*` 스크립트 무파손. 신규 `KEBAB_PDF_OCR_{DET_MODEL,REC_MODEL,DICT,SCORE_THRESH,UNCLIP_RATIO,MAX_BOXES}` 추가. - **load 시 메모리 내 자동 변환** — v3 는 최초의 non-additive rename 이라 미변환 v2 파일이 serde default 로 떨어지면 설정 유실. `Config::from_file` 이 `schema_version < 3` 파일을 디스크 미변경으로 메모리에서 변환해 유실 0. 파일 갱신은 여전히 `kebab config migrate`. ## 변경 카테고리 - **kebab-config**: `Config`/`IngestCfg` 재배치(leaf 구조체 불변), `PdfOcrCfg` paddle 대칭 6키, `ser_f32_clean`(f32 직렬화 찌꺼기 제거), `apply_env` RHS 갱신, `from_file` 자동 변환, `migrate::step_2_to_3`(테이블 relocation + paddle 값 복사 + 멱등), `key_comment`(per-option 주석). - **kebab-app / kebab-eval / kebab-parse-image**: `config.*` → `config.ingest.*` call-site sweep + `ocr_engine_version_for_sig` 미디어화. - **문서**: README Configuration([ingest.*] + migrate 안내), docs/SMOKE.md config 예시(v3), HOTFIXES dated entry, 선행 마이그레이션 spec 교차링크. workspace version 0.27.0→0.28.0(minor). ## 검증 - `cargo clippy --workspace --all-targets -j 8 -- -D warnings` → 0 warnings (리더 독립 재실행 EXIT=0). - `cargo test -p kebab-config -p kebab-app -p kebab-eval -j 8` → 전부 `test result: ok`, FAILED 0 (리더 독립 재실행 EXIT=0). ignored 소수는 라이브 Ollama 의존 기존 테스트로 본 변경 무관. - **무손실 골든**(`tests/migrate_v3.rs`): 사용자 실제 v2 config 의 값·주석·대안 줄 보존 + v3 파싱 일치 + 멱등. - **경계 케이스 직접 검증**: `[ingest.code]`로 implicit `[ingest]`가 이미 있는 상태 + 비기본 `[indexing]`(7/3/true) relocation → 스칼라가 sub-table 헤더 앞에 올바르게 직렬화, 값 전부 보존, 유효 TOML. - **도그푸딩**: release 빌드로 사용자 실제 config `kebab config migrate`(11 changes, .bak 백업, 멱등) + 재색인 0 실증(v2 자동변환·v3 디스크 양 경로 모두 unchanged). ## 시험 항목 (Test Plan) - [ ] 기존 `KEBAB_CHUNKING_*` / `KEBAB_IMAGE_OCR_*` env 가 새 경로로 정상 반영 - [ ] v2 config 로 `kebab ingest` → 재색인 0 - [ ] `kebab config migrate` 멱등 Assisted-by: Claude Code
altair823 added 11 commits 2026-06-04 13:29:26 +00:00
Config 의 indexing/chunking/image/pdf top-level 필드를 ingest: IngestCfg
하나로 통합. leaf 구조체는 불변, 부모 경로만 [ingest.*] 하위로 이동.
PdfOcrCfg 에 paddle 대칭 6키(det/rec/dict/score_thresh/unclip_ratio/
max_boxes) 추가. ser_f32_clean 으로 f32 직렬화 정리(0.3000000119→0.3).
apply_env RHS 를 self.ingest.* 로 갱신(env 키 문자열 LHS 불변).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
부모 경로에 .ingest 삽입(leaf 구조체 불변). src + 테스트 call-site 전부.
kebab-cli 테스트의 v2 TOML fixture 는 from_file 자동변환(T6) 경로 검증용으로 유지.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ocr_engine_version_for_sig 가 det/rec/dict 를 호출자(미디어별)로부터 받도록
인자화 — image 는 [ingest.image.ocr], pdf 는 [ingest.pdf.ocr]. v2 의 pdf↔image
paddle 비대칭 제거. engine_version_for_paths 신설(kebab-parse-image). 출력
문자열은 값 기반이라 v2 와 바이트 동일(불변식 #1). test seam + 골든 추가.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
annotate_table 의 leaf 분기 추가: 스칼라/배열 키 값 뒤에 한 줄 주석 suffix.
dotted path → 주석 매핑(workspace.root, ocr.model, request_timeout 등).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
move_table(decor 포함 통째 이동) + move_indexing_keys(병렬도 키) +
copy_image_paddle_to_pdf(v2 비대칭 보존). CURRENT_SCHEMA_VERSION=3.
section_comment 를 ingest.* 경로로 갱신. 멱등.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
schema_version < CURRENT 이면 migrate_document 경유로 메모리에서 변환 후 파싱.
디스크 파일은 불변(갱신은 kebab config migrate). 일회성 warn. 불변식 #3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
사용자 실제 config(주석·대안 줄·score_gate=0.3000…1192 포함)를 fixture 로.
값·주석 보존 + v3 파싱 일치 + 멱등 검증.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
apply_env whitelist 의 키 문자열(LHS) 전부 불변, 대입 대상만 self.ingest.*
(불변식 #2). KEBAB_PDF_OCR_{DET_MODEL,REC_MODEL,DICT,SCORE_THRESH,
UNCLIP_RATIO,MAX_BOXES} 신규(image.ocr paddle 패턴 대칭).
게이트: clippy --workspace --all-targets 0, kebab-config/app/eval 테스트 green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
README Configuration([ingest.*] 레이아웃 + migrate 안내), SMOKE config 예시,
HOTFIXES dated entry(rename 매핑 + 3 불변식), 선행 마이그레이션 spec 교차링크.
인터페이스 변경(config 레이아웃 rename + env 추가) = minor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
도그푸딩(release 빌드): 사용자 실제 v2 config 변환(값·주석 보존·멱등) +
재색인 0 실증(v2 자동변환·v3 디스크 양 경로 unchanged). v0.28.0 release notes
draft(변경/trade-off/mitigation/upgrade 4단락).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
claude-reviewer-01 requested changes 2026-06-04 13:32:02 +00:00
Dismissed
claude-reviewer-01 left a comment
Member

회차 1 — 구현 견고, 게이트(clippy/test) 리더 독립 재실행 green, 경계 케이스(implicit [ingest] + 비기본 [indexing]) 직접 검증 통과, 무손실 골든이 사용자 실제 v2 config 를 fixture 로 사용. 3대 불변식(signature 바이트 불변/env 이름 보존/load 자동변환) 모두 테스트+도그푸딩으로 고정. signature 미디어화(det/rec/dict 인자화로 pdf↔image 비대칭 제거)와 toml_edit relocation 의 decor 보존이 깔끔. actionable 은 LOW 1건(from_file 이중 toml 파싱)뿐 — 반영 후 APPROVE 예정. 관찰 1건은 수정 불요.

회차 1 — 구현 견고, 게이트(clippy/test) 리더 독립 재실행 green, 경계 케이스(implicit [ingest] + 비기본 [indexing]) 직접 검증 통과, 무손실 골든이 사용자 실제 v2 config 를 fixture 로 사용. 3대 불변식(signature 바이트 불변/env 이름 보존/load 자동변환) 모두 테스트+도그푸딩으로 고정. signature 미디어화(det/rec/dict 인자화로 pdf↔image 비대칭 제거)와 toml_edit relocation 의 decor 보존이 깔끔. actionable 은 LOW 1건(from_file 이중 toml 파싱)뿐 — 반영 후 APPROVE 예정. 관찰 1건은 수정 불요.
@@ -924,0 +991,4 @@
// 설정 유실 없이 로드(불변식 #3). non-additive relocation(v2→v3) 은
// serde default forward-compat 로는 커버 안 되므로 반드시 거쳐야 한다.
let parse_text = {
let from = toml::from_str::<toml::Value>(&text)

[LOW] from_file 가 같은 texttoml::Value 로 두 번 파싱한다 — 위(972줄)의 workspace.include deprecation probe 와 여기(994줄)의 schema_version 감지. config load 는 매 CLI 호출마다 일어나므로, 두 probe 를 한 번의 toml::from_str::<toml::Value>(&text) 결과를 재사용하도록 합치면 파싱 1회를 아낄 수 있다. 기능엔 영향 없는 정리.

[LOW] `from_file` 가 같은 `text` 를 `toml::Value` 로 두 번 파싱한다 — 위(972줄)의 `workspace.include` deprecation probe 와 여기(994줄)의 `schema_version` 감지. config load 는 매 CLI 호출마다 일어나므로, 두 probe 를 한 번의 `toml::from_str::<toml::Value>(&text)` 결과를 재사용하도록 합치면 파싱 1회를 아낄 수 있다. 기능엔 영향 없는 정리.
@@ -194,0 +310,4 @@
/// v3: pdf paddle 동작 보존. v2 는 pdf paddle 이 `[image.ocr]` 의 모델 경로를
/// 빌려썼다. relocation 후 image.ocr 의 paddle 6키 실제 값을 pdf.ocr 대칭
/// 키로 복사한다(pdf 가 이미 명시한 키는 덮어쓰지 않음, pdf 가 paddle 일 때만).
fn copy_image_paddle_to_pdf(doc: &mut DocumentMut) {

(관찰, 수정 불요) copy_image_paddle_to_pdf 가 pdf engine=paddle-onnx 일 때만 image paddle 6키를 복사하고 pdf 가 이미 명시한 키는 보존 — v2 의 'pdf 가 image paddle 을 빌려쓰던' 동작을 정확히 보존하는 좋은 처리. 재색인 0 도그푸딩으로 실증됨.

(관찰, 수정 불요) `copy_image_paddle_to_pdf` 가 pdf engine=paddle-onnx 일 때만 image paddle 6키를 복사하고 pdf 가 이미 명시한 키는 보존 — v2 의 'pdf 가 image paddle 을 빌려쓰던' 동작을 정확히 보존하는 좋은 처리. 재색인 0 도그푸딩으로 실증됨.
altair823 added 1 commit 2026-06-04 13:33:13 +00:00
claude-reviewer-01 approved these changes 2026-06-04 13:33:26 +00:00
claude-reviewer-01 left a comment
Member

회차 2 — 회차 1 의 actionable(LOW: from_file 이중 toml::Value 파싱) 반영 확인: let probe = toml::from_str::<toml::Value>(&text).ok(); 한 번으로 include probe + schema_version 감지 공유(fdf09c3). kebab-config clippy/test 재실행 green. 남은 actionable 0, 관찰 1건은 수정 불요(설계 의도). 머지 동의.

회차 2 — 회차 1 의 actionable(LOW: from_file 이중 toml::Value 파싱) 반영 확인: `let probe = toml::from_str::<toml::Value>(&text).ok();` 한 번으로 include probe + schema_version 감지 공유(fdf09c3). kebab-config clippy/test 재실행 green. 남은 actionable 0, 관찰 1건은 수정 불요(설계 의도). 머지 동의.
altair823 merged commit 403e162ac0 into main 2026-06-04 14:36:44 +00:00
altair823 deleted branch feat/config-schema-reorg 2026-06-04 14:36:46 +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#207