# Plan closure round 1 — 한국어 morphological tokenizer

**Verdict**: ACCEPT
**Reviewed by**: closure verifier (sonnet)
**Reviewed at**: 2026-05-28

---

## Task A — Step → Spec traceability matrix

### Forward matrix (Step → Spec sections)

| Step | Title | Plan 에 명시된 Spec sections | Spec content match? | Notes |
|---|---|---|---|---|
| S1 | V009 migration + design §5.5 + CI rename | §5.1, §5.2, §5.3 | ✅ | spec §5.1 DDL skeleton, §5.2 corpus_revision bump SQL, §5.3 design §5.5 갱신 + CI diff-check rename 정확히 cover. |
| S2 | lindera dep | §6.1, §10.1 | ✅ | spec §6.1 라이브러리 선정 (lindera + lindera-dict-ko-dic), §10.1 license 검증 + Appendix D cross-link 반영. |
| S3 | tokenize_korean_morphological + ingest 통합 | §6.2 | ✅ | spec §6.2 Pre-tokenize 우회 + Invariant + 실패 처리 전체 cover. chunk struct 신규 field + store INSERT path 포함. |
| S4 | first-boot eager backfill | §8.1, §8.2, §6.2 (backfill atomic transaction) | ✅ | spec §8.1 V007 trigram DROP 처리, §8.2 자동 eager backfill 전략, §6.2 의 backfill atomic transaction invariant 모두 cover. |
| S5 | short_query_hint 제거 + lexical.rs 정리 | §7.2, §7.3 | ✅ | spec §7.2 lexical.rs 조정 (보존 선택), §7.3 CLI hint 제거 범위 cover. wire schema 영향 확인 절차(§11.3 cross-check)도 포함. |
| S6 | lexical_index_version bump | §11.1, §11.3 | ✅ | spec §11.1 index_version bump (format 갱신), §11.3 wire content 변화 명시 (lexical test 갱신) cover. |
| S7 | 신규 unit/integration test | §9.1, §9.2 | ✅ | spec §9.1 lexical-mode scenarios 4개 중 한국어 3개 + 영어 회귀 1개, §9.2 test 시그니처 verbatim 반영. fts_v009_matches_design_section_5_5_verbatim 은 S1 에서 이미 생성됨(plan 내 명시). |
| S8 | eval golden regenerate | §11.3 | ✅ | spec §11.3 "eval golden baseline 재생성 필수" 를 plan scope 포함으로 결정 + deviation 시 P5 follow-up 분리 가능 명시. |
| S9 | docs sync | §7.4 | ✅ | spec §7.4 Surface cascade list (README / SKILL / HANDOFF / ARCHITECTURE) + tasks/HOTFIXES.md entry 모두 cover. |
| S10 | version bump | §12.1 | ✅ | spec §12.1 v0.20.1 patch release strategy (Cargo.toml version bump + release notes draft) cover. |
| S11 | final sanity | §9.3, §12.2 | ✅ | spec §9.3 verifier checklist + §12.2 dogfood verification cover. |

### Reverse matrix (Spec section → 커버 여부)

| Spec section | Title | Cover 여부 | 담당 Step |
|---|---|---|---|
| §1 Summary | 배경 요약 | 직접 step 불필요 (서술) | — |
| §2 Background (§2.1~§2.3) | V007 한계 + 도그푸딩 + HOTFIXES 맥락 | 직접 step 불필요 (서술) | — |
| §3 Goals + Non-Goals | 목표 범위 | 직접 step 불필요 (서술) | — |
| §4 Design Decision (§4.1~§4.2) | Option A 선택 | 직접 step 불필요 (설계 결정) | — |
| §5.1 DDL skeleton | V009 migration SQL | ✅ covered | S1 |
| §5.2 corpus_revision bump | kv UPDATE + search cache 무효화 | ✅ covered | S1 |
| §5.3 Design contract 변경 + CI diff-check | §5.5 갱신 + test rename | ✅ covered | S1 |
| §6.1 라이브러리 선정 | lindera + lindera-dict-ko-dic | ✅ covered | S2 |
| §6.2 Pre-tokenize 우회 + Invariant + 실패 처리 | tokenize helper + ingest 통합 + backfill | ✅ covered | S3, S4 |
| §6.3 Vendoring 전략 | feature flag (default-enabled) | ⚠ PARTIAL | S2 에서 workspace dep 추가는 cover 하나, `kebab-app/[features]` 의 feature gate 등록(§6.3 "fts_korean_morphological = ["lindera"]") 이 plan 의 어떤 step 에도 **명시적으로 언급되지 않음**. |
| §7.1 Search CLI 경로 (변경 없음) | query path 변경 없음 | 직접 step 불필요 (서술) | — |
| §7.2 lexical.rs 조정 | build_match_string() 단순화 검토 | ✅ covered | S5 |
| §7.3 CLI hint 제거 | short_query_hint 제거 | ✅ covered | S5 |
| §7.4 Surface cascade list | docs sync | ✅ covered | S9 |
| §8.1 기존 V007 처리 | DROP + V009 교체 | ✅ covered | S4 |
| §8.2 자동 eager backfill | first-boot hook + idempotency | ✅ covered | S4 |
| §9.1 Lexical-mode search scenarios | 4 AC scenario | ✅ covered | S7, S11 |
| §9.2 Test coverage | test 시그니처 | ✅ covered | S7 |
| §9.3 Verifier checklist | final checklist | ✅ covered | S11 |
| §10.1 License verification | cargo deny / SPDX | ✅ covered | S2 |
| §10.2 Dict size + binary bloat | binary 크기 실측 | ✅ covered (evidence 는 S2 에서 cargo tree + 실측 reconcile) | S2 |
| §10.3 Ingest latency 증가 | latency 측정 | plan S5~Risk 절에 mitigation 언급 (formal step 없음, 허용 범위) | S11 |
| §10.4 다른 언어 | 별 PR | 직접 step 불필요 (out of scope 명시) | — |
| §11.1 index_version bump | lexical_index_version 함수 갱신 | ✅ covered | S6 |
| §11.2 parser/chunker_version | 변경 없음 | 직접 step 불필요 (서술) | — |
| §11.3 Wire schema 변경 + hit ordering | wire shape 불변 + eval golden | ✅ covered | S6, S8 |
| §12.1 v0.20.1 patch release | version bump + release notes | ✅ covered | S10 |
| §12.2 Dogfood verification | fresh KB + 2자 query | ✅ covered | S11 |
| Appendix A (Option B/C 비교) | 설계 rationale | 직접 step 불필요 (서술) | — |
| Appendix B (segmentation evidence) | lindera 실측 | S3 의 test fixture + mitigation 에서 반영 | S3 |
| Appendix C (cost evidence) | binary/DB/latency 추정 | S2 의 cargo build 실측 + plan §10 risks 에서 반영 | S2 |
| Appendix D (license) | SPDX 검증 | ✅ covered | S2 |

**누락 section 발견**: §6.3 의 feature flag (`fts_korean_morphological`) 등록이 plan 어디에도 명시적 step/task 가 없음. 아래 Task B 와 연계하여 micro-patch 권장.

---

## Task B — AC actionability (per step)

| Step | AC text excerpt | Actionable? | 비고 / 권장 수정 |
|---|---|---|---|
| S1 | `cargo test -p kebab-store-sqlite --test fts fts_v009_matches_design_section_5_5_verbatim -j 4` → exit 0 | ✅ | 명령 + 기대 결과 명확. |
| S1 | `cargo test -p kebab-store-sqlite --test fts v009_bumps_corpus_revision -j 4` → exit 0, corpus_revision 값 strict-monotonic 증가 | ✅ | "strict-monotonic 증가" 는 `SELECT v` 값이 V008 적용 시점 대비 +1 이상 = verifier 가 SQL query 로 확인 가능. |
| S1 | `grep -c "fts_v007_matches_design_section_5_5_verbatim" crates/kebab-store-sqlite/tests/fts.rs` → `0` | ✅ | grep count 0 = rename 완료 mechanical 확인. |
| S1 | `cargo clippy -p kebab-store-sqlite --all-targets -j 4 -- -D warnings` → clean | ✅ | exit code 0 = clean. |
| S2 | `cargo build --workspace -j 4 2>&1 \| grep -E "^error\[E" \| wc -l` → `0` | ✅ | 명확한 명령 + wc -l 0 check. |
| S2 | `cargo tree --depth 1 -p lindera -p lindera-dict-ko-dic 2>&1 \| grep -iE "MIT\|Apache" \| wc -l` → `≥ 2` | ✅ | SPDX license 포함 여부 mechanical check. |
| S2 | `grep -c "lindera" Cargo.toml` → `≥ 1` | ✅ | |
| S2 | `grep -c "lindera" crates/kebab-chunk/Cargo.toml` → `≥ 1` | ✅ | |
| S3 | `cargo test -p kebab-chunk --test tokenize_korean tokenize_korean_morphological_splits_2char_word -j 4` → exit 0, token `"한국"` 포함 | ✅ | 명령 + fixture 명시. |
| S3 | `cargo test -p kebab-chunk --test tokenize_korean tokenize_korean_morphological_empty_returns_none -j 4` → exit 0 | ✅ | |
| S3 | `cargo build --workspace -j 4 2>&1 \| grep -c "warning: unused"` 가 baseline 대비 증가하지 않음 | ⚠ PARTIAL | "baseline 대비" 가 verifier 가 별도로 baseline 수치를 보유하고 있어야 함. 더 actionable 한 형태: `cargo build --workspace -j 4 2>&1 \| grep -c "warning: unused import.*lindera"` → `0` (lindera 가 실제 사용됨) 으로 수정 권장. |
| S3 | `grep -n "tokenized_korean_text" crates/kebab-chunk/src/lib.rs` → `≥ 1` | ✅ | |
| S3 | `cargo clippy -p kebab-chunk --all-targets -j 4 -- -D warnings` → clean | ✅ | |
| S4 | `cargo test -p kebab-store-sqlite --test fts backfill_tokenized_korean_text_populates_nullable_rows -j 4` → exit 0, idempotency 확인 | ✅ | idempotency 는 test body 에서 두 번째 호출 반환값 0 확인으로 mechanical 검증. |
| S4 | `App::open_with_config` 두 번 연속 호출 시 두번째 backfill_count = 0 | ⚠ PARTIAL | 이 AC 는 unit test 명령이 없음. "두 번 연속 호출" 의 test binary 이름이 명시되지 않아 verifier 가 어느 test 로 확인하는지 불명확. 권장: `cargo test -p kebab-app -j 4 -- backfill_idempotent` (또는 동급 test 명) 으로 명시. |
| S4 | `cargo clippy -p kebab-app --all-targets -j 4 -- -D warnings` → clean | ✅ | |
| S5 | `grep -rn "short_query_hint" crates/ tests/ 2>/dev/null \| wc -l` → `0` | ✅ | doc-comment 1줄 허용 예외가 있으나 ≤1 조건으로 처리 가능. |
| S5 | `cargo build --workspace -j 4 2>&1 \| grep -E "error\|warning: unused" \| wc -l` → baseline 과 동등 | ⚠ PARTIAL | S3 AC 와 동일한 "baseline 대비" 문제. 권장: `cargo build --workspace -j 4 2>&1 \| grep -E "^error" \| wc -l` → `0` 으로 대체. |
| S5 | `cargo test -p kebab-cli --test wire_search_response -j 4` → exit 0, test 가 list 에서 사라짐 | ✅ | test list 에서 사라짐 = `cargo test -- --list` grep 으로 확인. |
| S5 | `cargo clippy --workspace --all-targets -j 4 -- -D warnings` → clean | ✅ | |
| S6 | `cargo test -p kebab-search --test lexical lexical_index_version_is_returned_unchanged -j 4` → exit 0 | ✅ | |
| S6 | `./target/debug/kebab schema --json \| jq -r '.index_versions.lexical // empty' 2>/dev/null \| grep -c "fts5-v009"` → `≥ 1` | ⚠ PARTIAL | `target/debug/kebab` 의 빌드 여부가 이 step 에서 보장되지 않음. 권장: 명령 앞에 `cargo build -p kebab-cli -j 4 && ` 를 prepend 하거나, release path 용 `cargo build --release -p kebab-cli -j 4` 선행 명시. |
| S6 | `cargo clippy -p kebab-app --all-targets -j 4 -- -D warnings` → clean | ✅ | |
| S7 | `cargo test -p kebab-store-sqlite --test fts fts_v009_korean_morphological_2char_query_hits -j 4` → exit 0 | ✅ | |
| S7 | `cargo test -p kebab-store-sqlite --test fts fts_v009_english_whole_token_only -j 4` → exit 0 | ✅ | |
| S7 | `cargo test -p kebab-app --test search_korean korean_morphological_2char_query_lexical_mode -j 4` → exit 0 | ✅ | |
| S7 | `cargo test -p kebab-app --test search_korean korean_morphological_mixed_english_korean_query -j 4` → exit 0 | ✅ | |
| S7 | 신규 test binary 2개 추가로 workspace test count baseline +4 이상 | ⚠ PARTIAL | 검증 명령이 없음. 권장: `cargo test --workspace --no-fail-fast -j 1 2>&1 \| grep "^test result" \| awk -F'[,;]' '{sum+=\$2} END{print sum}'` 의 before/after 비교, 또는 `cargo test -p kebab-store-sqlite --test fts -- --list \| wc -l` 과 `cargo test -p kebab-app --test search_korean -- --list \| wc -l` 각 ≥ 1 로 대체 가능. |
| S8 | `cargo test -p kebab-eval -j 4 2>&1 \| grep "test result.*failed" \| grep -v "0 failed" \| wc -l` → `0` | ✅ | |
| S8 | `git diff --stat crates/kebab-eval/goldens/` → 변경 라인 수 > 0 | ✅ | baseline 이 실제로 갱신됐는지 mechanical 확인. |
| S8 | `cargo clippy -p kebab-eval --all-targets -j 4 -- -D warnings` → clean | ✅ | |
| S9 | `git diff --stat README.md HANDOFF.md docs/ARCHITECTURE.md integrations/claude-code/kebab/SKILL.md tasks/HOTFIXES.md` → 5 file 모두 변경 | ✅ | |
| S9 | `grep -c "한국어 2자" README.md` → `≥ 1` | ✅ | |
| S9 | `grep -c "V009" tasks/HOTFIXES.md` → `≥ 1` | ✅ | |
| S9 | `grep -c "lindera" docs/ARCHITECTURE.md` → `≥ 1` | ✅ | |
| S10 | `grep "^version" Cargo.toml \| head -1` → `version = "0.20.1"` | ✅ | |
| S10 | `./target/release/kebab --version 2>&1` → `kebab 0.20.1` | ⚠ PARTIAL | release binary 빌드 여부가 S10 에서 보장되지 않음. 권장: `cargo build --release -p kebab-cli -j 4 && ./target/release/kebab --version` 로 명시. |
| S10 | `cargo build --workspace -j 4 2>&1 \| tail -3` → success | ✅ | |
| S11 | `cargo test --workspace --no-fail-fast -j 1` → 모두 pass (baseline +4 이상) | ✅ | S11 은 전체 suite run — workspace sanity 기준. |
| S11 | dogfood smoke (fresh KB, 3 query) | ✅ | 명령 verbatim 명시됨. |
| S11 | V007 snapshot backfill 시나리오 | ✅ (best-effort 명시) | snapshot 부재 시 best-effort 허용으로 명시됨. |

**요약**: PARTIAL AC 총 6건 (S3, S4, S5, S6, S7, S10) — 모두 minor actionability gap 이며, 명령 보강으로 해소 가능. NEEDS_REWRITE 수준 아님 → micro-patch 권장.

---

## Task C — Dependencies sanity

### 그래프 cycle-free 여부

의존 관계를 DAG 로 표현:

```
S1, S2 → S3 → S4, S5, S6 → S7 → S8 → S9 → S10 → S11
         (S1 also → S4, S6, S7 directly)
```

- S1 → S3 (V009 schema 필요), S1 → S4 (backfill은 V009 schema 필요), S1 → S6 (verbatim test rename 결과), S1 → S7 (fts.rs V009 test 기반).
- S2 → S3 (lindera dep 필요).
- S3 → S4 (backfill API 가 tokenize_korean_morphological 호출), S3 → S5 (short_query_hint 제거 후 cascade clean 필요), S3 → S7 (search_korean 통합 test 의 ingest path).
- S4, S5, S6 → S7 (test가 backfill + hint 제거 + version bump 모두 의존).
- S7 → S8 (eval golden 재생성은 new test baseline 기반), S7 → S11.
- S8 → S11.
- S9 → S10 (docs sync 후 version bump 의 커밋 순서).
- S10 → S11.

사이클 없음 (topological order: S1 → S2 → S3 → {S4, S5, S6} → S7 → S8 → S9 → S10 → S11). **그래프 cycle-free: ✅**

### parallel-dispatch 가능 step 명시 정확성

plan §3 의 명시:
- **Group 1**: S1 + S2 병렬. ✅ 두 step 은 파일 overlap 없음 (S1은 migration+design+fts.rs, S2는 Cargo.toml 만).
- **Group 2**: S4 + S5 + S6 병렬. ✅ S4 (store.rs + lib.rs), S5 (app.rs + tui/*.rs + cli/tests), S6 (app.rs:991-993 한 줄) — file overlap이 app.rs 에서 발생할 수 있음. S5 는 `crates/kebab-app/src/app.rs:98,532,616` 를 수정하고, S6 은 `crates/kebab-app/src/app.rs:991-993` 을 수정 — 동일 파일의 다른 행이나 **병렬 에이전트가 동시에 수정 시 merge conflict 가능**. plan 이 "file overlap 0" 이라고 명시하나 실제로는 app.rs 가 공유됨. 이는 runtime conflict risk 이며 cycle 이 아니므로 NEEDS_REWRITE trigger 아님. micro-patch 권장: Group 2 의 S6 을 S5 직후 sequential 로 명시하거나, "app.rs 의 편집 구역 분리 (line 범위 기준)" 를 executor 에게 주의 사항으로 기록.

### subagent-driven-development "tasks mostly independent" criterion

- S1, S2 가 진정으로 독립적 (entry point, 파일 무중복). ✅
- S4, S5 는 파일 overlap 최소 (서로 다른 crate). ✅
- S4/S5 vs S6 는 app.rs 공유 — conditional ✅ (행 단위 비겹침이나 실측 merge 주의 필요).
- S7 → S8 → S9 → S10 은 sequential 이므로 독립성 불요.

전반적으로 "tasks mostly independent" criterion 충족. ✅

---

## Task D — Cost optimization 정합성

| Step | Title | Plan 권장 모델 | 사용자 요청 부합 | 판단 |
|---|---|---|---|---|
| S1 | V009 migration + design §5.5 + CI rename | **opus** | 복잡: spec §5.5 verbatim 정합 + CI diff-check marker 형식 일관성 + design doc 갱신. trigger CASE expression 한 글자 오차로 CI fail 위험. | ✅ opus 적절 |
| S2 | lindera dep | sonnet | 단순 mechanical: Cargo.toml dep 추가 + cargo tree SPDX 확인. | ✅ sonnet 적절 |
| S3 | tokenize_korean_morphological + ingest 통합 | **opus** | 복잡: lindera API 호출 (0.32 builder pattern 확인), chunk struct cascade, multi-crate 동시 변경, transaction invariant 보장. | ✅ opus 적절 |
| S4 | first-boot eager backfill | sonnet | spec 에 API signature 와 body outline 이 상세 명시됨. batch commit 패턴 표준. | ✅ sonnet 적절 |
| S5 | short_query_hint 제거 + lexical.rs 정리 | sonnet | 다중 파일 cascade 이나 mechanical search+delete. wire schema grep + if-then 분기 있으나 명시됨. | ✅ sonnet 적절 |
| S6 | lexical_index_version bump | sonnet | 단일 함수 + test fixture 1줄 갱신. | ✅ sonnet 적절 |
| S7 | 신규 test | sonnet | spec §9.2 verbatim 시그니처 따라. fixture 조정 필요 시 plan 에 가이드 있음. | ✅ sonnet 적절 |
| S8 | eval golden regenerate | sonnet | baseline regenerate 명령 실행 + commit. | ✅ sonnet 적절 |
| S9 | docs sync | sonnet | mechanical text edit, README narrow scope 지켜짐. | ✅ sonnet 적절 |
| S10 | version bump | sonnet | 한 줄 변경. | ✅ sonnet 적절 |
| S11 | final sanity | sonnet | 검증 명령 실행만. | ✅ sonnet 적절 |
| PR-level final review | 전체 diff | **opus** | merge 직전 cross-file 일관성. | ✅ opus 적절 |

**종합**: 사용자 요청("가벼운 작업은 sonnet, 복잡한 것은 opus") 과 plan 의 routing 이 완전히 일치. S1 (§5.5 verbatim), S3 (lindera API + multi-crate) 두 step 만 opus 로 격상, 나머지 9 step 은 sonnet. ✅ 정합 이상 없음.

---

## Task E — 0 new substantive finding

plan 이 spec 의 design decision 을 재해석·변경·추가했는지 mechanical 검토:

1. **§6.3 feature gate**: plan S2 의 구현 outline 은 workspace dep 추가를 기술하나, spec §6.3 의 `[features] fts_korean_morphological = ["lindera"]` 등록을 plan 의 어느 step 에도 명시하지 않았다. 이는 spec design 을 **변경**한 것이 아니라 **누락**한 것이다 (Task A 에서도 PARTIAL 로 분류). design 재해석이 아니므로 substantive finding 에는 해당하지 않는다.

2. **S4.1 의 backfill batch commit (1000 row 마다)**: spec §8.2 에서 batch 크기를 구체적으로 명시하지 않았고 plan 이 1000 row 로 구체화했다. 이는 implementation detail 의 구체화이며, spec 의 design decision (backfill 정책 자체, idempotency, atomic transaction) 을 변경하지 않았다. substantive finding 아님.

3. **S10.3 의 release notes draft 파일 (`docs/release-notes/v0.20.1-draft.md`)**: spec §12.1 의 release notes 4 단락 본문이 plan 에서 별도 파일 보관으로 구체화됐다. spec 의 release strategy 를 변경하지 않는 implementation 선택. substantive finding 아님.

4. **S5 의 `search_plain_emits_short_query_hint_to_stderr` test 처리**: plan S5.5 에서 "삭제 또는 inverted rename" 두 가지 선택지를 열어 뒀다. spec §7.3 은 함수 정의+호출 제거 범위만 명시하고 test 처리를 직접 다루지 않으므로, plan 이 spec design 을 변경한 것이 아니라 executor 에게 선택을 위임한 것이다. substantive finding 아님.

5. **S3.1 의 `OnceCell` / `lazy_static` tokenizer 캐시 패턴**: spec §6.2 에는 dictionary load 의 캐시 패턴이 명시되지 않았다. plan 이 performance optimization 을 추가 제안했으나, 이는 spec 의 invariant ("동일 Rust transaction 내 INSERT") 를 위반하지 않는 implementation hint 다. design 추가가 아니라 실행 guidance. substantive finding 아님.

**None.** — 새로운 substantive finding 없음.

---

## Task F — Final verifier checklist completeness

### spec §9 AC 커버

| spec §9 항목 | plan §7 checklist 커버 | 비고 |
|---|---|---|
| §9.1 Scenario 1: `kebab search '한국'` → hit ≥ 1 | ✅ `kebab search '한국'` (fresh V009 KB) → hit ≥ 1 | |
| §9.1 Scenario 2: `kebab search '서울'` → hit ≥ 1 | ✅ `kebab search '서울'` (fresh V009 KB) → hit ≥ 1 | |
| §9.1 Scenario 3: `kebab search '지하철'` → hit ≥ 1 | ✅ `kebab search '지하철'` (fresh V009 KB) → hit ≥ 1 | |
| §9.1 Scenario 4: `kebab search 'pipeline'` → whole-token 매칭만 (substring 0-hit) | ⚠ PARTIAL | plan checklist 에 `pipeline` 검색 확인이 없음. S11.5 dogfood smoke 에 해당 query 없음. |
| §9.2 `fts_v009_korean_morphological_2char_query_hits` pass | ✅ `cargo test --workspace --no-fail-fast -j 1` → baseline +4 이상 에 포함 | |
| §9.2 `fts_v009_english_whole_token_only` pass | ✅ 동상 | |
| §9.2 `fts_v009_matches_design_section_5_5_verbatim` pass | ✅ 동상 (S1 에서 생성됨) | |
| §9.2 `korean_morphological_2char_query_lexical_mode` pass | ✅ 동상 | |
| §9.2 `korean_morphological_mixed_english_korean_query` pass | ✅ 동상 | |
| §9.3 `chunks.tokenized_korean_text` 모든 한국어 chunk 에 채워짐 | ✅ V009 migration apply 후 기존 V007 KB → eager backfill 확인 | |
| §9.3 FTS5 query `MATCH "한국"` → hit | ✅ 상동 | |
| §9.3 `kebab schema --json` wire schema 변경 없음 | ✅ S11.4 schema 무결성 (`jq -e '.wire.schemas \| length'`) | |
| §9.3 Hybrid/vector search 변경 없음 | ⚠ PARTIAL | plan checklist 에 hybrid/vector mode 회귀 검증 명령이 없음. spec §9.3 "Hybrid/vector search 는 변경 없음" 항목을 S11 의 dogfood smoke 에서 별도 확인하도록 명시되지 않음. |

### spec §10 risk 커버

| spec §10 risk | plan checklist 커버 | 비고 |
|---|---|---|
| §10.1 License (cargo deny) | ✅ "(deferred to P9) cargo deny check" 명시 + cargo tree SPDX 수동 대체 | |
| §10.2 Dict size + binary bloat | ⚠ PARTIAL | plan checklist 에 binary size 실측 확인 항목 없음. S2 에서 cargo build 출력 확인은 있으나, release binary 의 `ls -lh` 또는 `size` 측정이 checklist 에 없음. |
| §10.3 Ingest latency 증가 | ⚠ PARTIAL | plan checklist 에 ingest latency 측정 항목이 없음. spec §12.2 "Performance measurement: ingest duration 전후 비교" 를 plan §7 checklist 가 cover 하지 않음. |
| §10.4 일본어/중국어 | 직접 check 불필요 (out of scope) | ✅ |

### spec §12 release strategy 커버

| spec §12 항목 | plan checklist 커버 | 비고 |
|---|---|---|
| §12.1 v0.20.1 version bump | ✅ `Cargo.toml workspace version = "0.20.1"` | |
| §12.1 release notes 4 단락 | ✅ `docs/release-notes/v0.20.1-draft.md` 4 단락 | |
| §12.2 fresh KB + 2자 query dogfood | ✅ S11.5 smoke | |
| §12.2 hybrid/vector mode 변경 없음 확인 | ⚠ PARTIAL | 상동 (§9.3 과 동일 gap) |
| §12.2 performance measurement | ⚠ PARTIAL | checklist 에 ingest duration 비교 없음 |

**누락 항목 요약:**
- English substring 0-hit 회귀 확인 (`'pipeline'` 또는 `'token'` query → 0-hit on substring-only string) — plan §7 checklist 미포함.
- Hybrid/vector search 변경 없음 확인 명령 — plan §7 checklist 미포함.
- Release binary size 실측 — plan §7 checklist 미포함 (spec §10.2 risk).
- Ingest latency 측정 — plan §7 checklist 미포함 (spec §12.2 + §10.3).

4건 모두 낮은 위험도의 검증 gap 이며, NEEDS_REWRITE trigger 수준 아님. micro-patch 로 처리 가능.

---

## Verdict rationale

Task A~F 의 결과를 종합한다:

- **Task A**: spec §6.3 feature flag 등록이 plan 에 누락됐으나, design 재해석이 아닌 implementation detail 누락이며 micro-patch 수준. spec 의 모든 core section (§5.1~§12.2) 이 적어도 한 step 에 의해 cover 됨.
- **Task B**: PARTIAL AC 6건이 모두 "baseline 대비" 모호성, binary 빌드 사전 보장 누락 등 minor actionability gap. 명령 1줄 추가로 해소 가능. critical AC vagueness ("올바르게 작동" 류) 는 0건.
- **Task C**: 그래프 cycle-free 확인. S5/S6 의 app.rs 공유로 인한 merge conflict 가능성이 있으나 plan 이 "file overlap 0" 이라고 잘못 명시한 것은 micro-patch 주의 수준. cycle 은 아님.
- **Task D**: 모든 model routing 이 사용자 요청("가벼운 작업 sonnet")과 정합. 이상 없음.
- **Task E**: 새로운 substantive design finding 없음. plan 은 spec 의 implementation 일정만 기술.
- **Task F**: 4건의 minor checklist gap (영어 substring 회귀 확인, hybrid/vector 회귀 확인, binary size, ingest latency). 모두 낮은 위험도.

NEEDS_REWRITE trigger (그래프 cycle, spec section 미커버, new substantive design 변경) 에 해당하는 항목 없음. **ACCEPT**.

---

## Recommended micro-patches (plan author 가 별 round 없이 직접 적용 가능)

다음은 plan 자체의 수정 없이 executor 에게 전달하거나, plan 의 해당 줄을 최소 보완하는 수준의 권장 사항이다.

**MP-1 (Task A, §6.3 feature flag)**: S2 또는 S3 의 "Files to modify" 에 `crates/kebab-app/Cargo.toml` — `[features]` 에 `fts_korean_morphological = ["dep:lindera"]` + `default = ["fts_korean_morphological"]` 추가 항목 삽입. spec §6.3 의 feature gate 등록을 누락하지 않도록.

**MP-2 (Task B, S3 AC)**: `cargo build --workspace -j 4 2>&1 \| grep -c "warning: unused"` → `cargo build --workspace -j 4 2>&1 \| grep -c "warning: unused import.*lindera"` → `0` 으로 수정.

**MP-3 (Task B, S4 AC)**: `App::open_with_config 두 번 연속 호출 시 backfill_count = 0` AC 에 구체적인 test 이름 또는 검증 명령 추가. 예: `cargo test -p kebab-app -j 4 -- backfill_is_idempotent_on_second_open` (또는 `backfill_tokenized_korean_text_populates_nullable_rows` 의 두번째 호출 assertion 이 이미 커버하는 경우 S4 AC 에 그 사실 cross-link).

**MP-4 (Task B, S5 AC)**: `cargo build --workspace -j 4 2>&1 \| grep -E "error\|warning: unused" \| wc -l` → `cargo build --workspace -j 4 2>&1 \| grep -E "^error" \| wc -l` → `0` 으로 대체.

**MP-5 (Task B, S6 AC)**: `./target/debug/kebab schema --json ...` 앞에 `cargo build -p kebab-cli -j 4 &&` 선행 명시.

**MP-6 (Task B, S7 AC)**: `신규 test binary 2개 추가로 workspace test count baseline +4 이상` 항목에 검증 명령 추가. 예: `cargo test -p kebab-store-sqlite --test fts -- --list 2>&1 \| grep "fts_v009_korean" \| wc -l` → `≥ 1` + `cargo test -p kebab-app --test search_korean -- --list 2>&1 \| wc -l` → `≥ 2`.

**MP-7 (Task B, S10 AC)**: `./target/release/kebab --version` 앞에 `cargo build --release -p kebab-cli -j 4 &&` 선행 명시.

**MP-8 (Task C, Group 2 주의)**: §3 Dependencies 의 Group 2 주의 사항에 "S5 와 S6 은 모두 `crates/kebab-app/src/app.rs` 를 수정함. 병렬 에이전트 실행 시 편집 행 범위를 사전 분리할 것 (S5: line 98,532,616; S6: line 991-993)." 한 줄 추가.

**MP-9 (Task F, §7 checklist)**: plan §7 verifier checklist 에 다음 3개 항목 추가:
- `./target/release/kebab --config /tmp/kebab-smoke-v009/config.toml search 'token' --json \| jq '.hits \| length'` → 0 (영어 substring 매칭 회귀 확인, V009 는 whole-token only).
- `./target/release/kebab --config /tmp/kebab-smoke-v009/config.toml search 'tokenizer' --json \| jq '.hits \| length'` → ≥ 1 (whole-token 매칭 정상).
- hybrid/vector 회귀: `./target/release/kebab --config /tmp/kebab-smoke-v009/config.toml search '한국' --mode hybrid --json \| jq '.hits \| length'` → ≥ 1 (또는 mode flag 실제 이름으로 대체).
