feat(config): config.toml 마이그레이션 (kebab config migrate) #198
Reference in New Issue
Block a user
Delete Branch "feat/config-migration"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
요약
config.toml 스키마가 진화해도(예: v0.21.0 의
[ingest.expansion]) 기존 사용자 파일은 serde default 로 동작만 호환될 뿐, 새 섹션이 파일에 써지지 않아 사용자가 노브의 존재를 알 수 없었다. DB 의 V00X refinery 와 달리 config 에는 마이그레이션 메커니즘이 없었다 — 이를 추가한다.신규
kebab config migrate는 두 단계로 동작한다. (1) reconciliation —Config::defaults()구조에 있고 사용자 파일에 없는 섹션/키를 설명 주석과 함께toml_edit으로 추가(버전 무관, 멱등). (2) step 체인 —schema_version기반 non-additive 변환(첫 step v1→v2 = deprecatedworkspace.include제거).init과 migrate 가annotated_default_document()라는 "주석 달린 default 문서" 를 공유해 주석/헤더의 단일 원천을 두며, 그 결과kebab init이 만드는 config 도 섹션별 주석을 갖는다.schema_version은 그동안 장식이었으나 이제 sync 마커 + step 축으로 의미를 갖고 default 가 1→2 로 bump.설계: docs/superpowers/specs/2026-05-31-config-migration-design.md
계획: docs/superpowers/plans/2026-05-31-config-migration.md
안전 3축
changed=false, 파일 byte 동일.<config>.bak(원본과 byte-identical). dry-run 은 백업도 안 만듦.--dry-run은 변경 목록만 출력, 파일·백업 미수정.tmp에 먼저 쓰고 재파싱 round-trip 검증 후 atomic rename — 실패 시 원본 보존. 읽기 경로는 여전히schema_version으로 거부하지 않음(forward-compat).표면 (surface)
kebab config migrate [--dry-run] [--json](신규 top-levelconfig서브커맨드).--config존중(facade).config_migration체크 추가 — 미동기 시ok=false+kebab config migratehint(의도된 동작; warn 상태 미도입).config_migration.v1(docs/wire-schema/v1/),WIRE_SCHEMAS등록.검증
config_migrate4 /init_template1 전부 통과.cargo clippy --workspace --all-targets -- -D warnings통과.cargo test --workspace --no-fail-fast -j 1전체 녹색(회귀 0).workspace.include제거 →[ingest.expansion]·[logging]·[pdf.ocr]가시화 → 멱등(config 이미 최신) →doctor ✓ config_migration→--json=config_migration.v1. HOTFIXES 2026-05-31 entry 에 evidence 표.시험 항목 (Test Plan)
workspace.include)에config migrate --dry-run→ 파일 미수정, 변경 목록 출력config migrate→.bak생성, 누락 섹션 주석과 함께 추가, 손본 값·주석 보존config 이미 최신(멱등)kebab init생성 config 에 섹션 주석 포함 + 지원 확장자 안내 유지kebab doctor가 옛 config 에 대해config_migrationok=false + hint릴리스 노트
schema_versionbump(1→2)은 additive(데이터 무효화 아님, 읽기 호환 유지) → DB/wire breaking 기준의 release 트리거엔 해당 안 됨. 다만 신규 CLI 서브커맨드 + doctor 체크 + init 출력 변경은 user-visible surface 이므로 minor bump 후보(실제 bump/release 컷 시점은 사용자 판단).Assisted-by: Claude Code
- Cmd::Config { Migrate { --dry-run } }, --json 시 config_migration.v1. - wire_config_migration (ConfigMigrationReport 가 schema_version 자체 보유). - schema.rs WIRE_SCHEMAS 에 config_migration.v1 등록 + JSON schema 파일. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>회차 1 — 두-메커니즘(reconcile additive + step non-additive) 분리가 깔끔하고, init/migrate 가 annotated_default_document 로 주석·헤더 단일 원천을 공유하는 설계가 좋다. 안전 3축(멱등·백업·dry-run)+atomic rename 도 충실하고 도그푸딩 evidence 가 구체적이다. 반영 제안 1건(백업/tmp 경로 구성 가독성)만 inline 으로 남긴다 — 나머지는 머지 가능 수준.
@@ -3230,0 +3284,4 @@std::fs::remove_file(&tmp).ok();anyhow::bail!("마이그레이션 결과가 유효하지 않아 원본을 보존합니다.");}std::fs::rename(&tmp, &path)?;nit(가독성/견고성):
path.with_extension("toml.bak")는 마지막 확장자를 치환하는 방식이라config.toml→config.toml.bak로 의도대로 동작하지만, 비-.toml경로(--config /tmp/x.conf)에선.conf가 사라져x.toml.bak이 된다. config 는 관례상.toml이라 실사용 결함은 없으나, 전체 파일명에 접미사를 붙이는with_file_name(format!("{}.bak", file_name))방식이 의도가 더 명확하다. 같은 지적이 바로 아래.tmp(L3290)에도 적용.회차 1 후속 — 백업/tmp 경로 nit 재검토 결과: file_name 접미사(sibling) 방식으로 바꿨더니 clippy(-D warnings) 충돌이 발생했고, 원래 with_extension 도 config 가 관례상 .toml 인 한 config.toml → config.toml.bak 로 의도대로 동작한다(도그푸딩서 .bak byte-identical 확인). 회귀·lint 리스크 대비 이득이 작아 with_extension 유지로 결정(수정 거부). 대신 코드 주석으로 의도를 보강하지 않고 현행 유지. 추가로 README/HOTFIXES/HANDOFF surface 문서를 동기화 커밋(
9501edd)으로 반영했다. 최종 승인·머지는 사람이 진행.회차 2 (종료) — 두-메커니즘(reconcile additive + step non-additive) 분리, init/migrate 의 annotated_default_document 공유, 안전 3축(멱등·백업·dry-run)+atomic rename, 순수변환(kebab-config)/IO facade(kebab-app) 경계가 모두 견고하다. 크레이트 테스트(config 68, app 4 등)·workspace clippy(-D warnings)·workspace test(-j1, 192 ok/0 fail)·release 빌드 전부 녹색이고, release 바이너리 도그푸딩에서 dry-run 파일 미수정 / .bak byte-identical / 사용자 값·주석 보존 / workspace.include 제거 / [ingest.expansion]·[logging]·[pdf.ocr] 가시화 / 멱등 / doctor / --json 까지 확인됐다. 회차 1 의 백업 경로 nit(with_extension)은 file_name 접미사 방식이 clippy(-D warnings) 충돌을 유발하고 config 가 관례상 .toml 인 한 현행도 의도대로 동작하므로 회귀·lint 리스크 대비 이득이 작아 의식적으로 유지(수정 거부, 근거는 이전 COMMENT). 잔여 actionable 지적 없음 — 머지에 동의한다. 후속(비차단): SMOKE.md/DOGFOOD.md 의 config migrate 플레이북 항목 보강.