Files
kebab/docs/superpowers/specs/2026-05-28-v0.20.x-korean-morphological-tokenizer-spec-critic-r2.md
altair823 8c56ef3010 docs(superpowers): v0.20.x C 한국어 morphological tokenizer spec + plan artifacts
본 commit 은 v0.20.x C task (Bug #8 — 한국어 2자 query 0-hit) 의
4-stage workflow artifact 5 파일을 archive:

- spec.md (668 line, status=accepted): Option A/B/C 비교 + lindera
  Path A (영어 substring 회귀 인정) 결정 + 12 section + 4 Appendix
  (B segmentation evidence, C cost evidence, D license evidence).
- spec-critic-r1.md: 3 critical + 6 major finding (NEEDS_REWRITE).
- spec-critic-r2.md: r1c rewrite 후 traceability matrix (ACCEPT).
- plan.md (750 line, status=accepted): 11 step + dependencies +
  cost optimization routing + 9 closure micro-patches 적용.
- plan-closure-r1.md: traceability matrix + 9 MP 의 origin.

이 artifact 들은 implementation 머지 후 frozen reference. 후속
deviation 은 tasks/HOTFIXES.md 가 source of truth.

Workflow stage:
1. spec drafter (omc team writer, opus)
2. spec critic R1 (omc team critic, opus) — NEEDS_REWRITE
3. spec rewriter r1c (omc team writer, opus) — 7 item fix
4. spec closure R2 (in-process verifier, sonnet) — ACCEPT
5. plan drafter (omc team planner, opus)
6. plan closure (in-process verifier, sonnet) — ACCEPT + 9 MP
7. subagent-driven-development implementation (11 step + 5 follow-up
   + 1 docs polish = 17 commit)
8. PR-level final code review (in-process code-reviewer, opus) —
   Approved with notes (4 minor docs finding, merge as-is)

Branch: feat/korean-morphological-tokenizer
Version: 0.20.1
2026-05-28 12:53:31 +00:00

12 KiB

Spec critic round 2 — 한국어 morphological tokenizer

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


Traceability matrix

Critic R1 Finding Severity Rewrite scope item Spec section(s) updated Status
#1 English regression critical Item 1 §3, §4.1, §4.2, §9.2, §12.1, Changelog resolved
#2 backfill claim critical Item 2 §8.2, §9.1, §12.1 resolved
#3 segmentation evidence critical Item 3 Appendix B + AC §9.1 cross-note resolved (scope-qualified)
#4 CI diff-check rename major Item 4 §5.3 resolved
#5 trigger race / transaction invariant major Item 4 §6.2 resolved
#6 storage evidence major Item 5 §4.1, §10.2, §10.3, Appendix C resolved (estimate, cross-linked)
#7 ordering/cache/cascade major Item 6 §5.2, §7.3, §7.4, §11.3 resolved
#8 config 노브 major Item 7 §6.3 (Option A — 노브 제거) resolved
#9 license evidence major Item 7 §10.1, Appendix D resolved

Finding 별 상세 확인

Finding #1: English substring 회귀

critic 의 권장: Path A (회귀 인정) 또는 Path B (dual-tokenizer) 중 하나 선택 후 §3/§4.1/§9.2 일관 갱신.

  • §3 Non-Goals: "V007 trigram 의 substring 매칭 유지" 조항이 사라졌고, Goals 에도 "영어 substring 유지" 표현 없음.
  • §4.1 표: English 영향 행이 "회귀 (substring → whole-token, V002 동일)" 으로 명시.
  • §4.2 (트레이드오프 절): Path A 선택 명시 + V007 부산물 영어 substring 제거 이유 설명.
  • §9.2 test: fts_v009_english_substring_retainedfts_v009_english_whole_token_only 로 rename 되고, assertion 이 'token' → 0-hit on tokenizer chunk 로 반전.
  • §12.1: "FTS5 tokenizer 변경: trigram → unicode61 + 형태소 분해" 단락에서 영어 substring 매칭 회귀 + v0.16.x 동작 환원 정직히 기술.

결론: §1 Summary 도 재확인 — "기존 trigram 의 장점(영어 substring 매칭, 부분 매칭 지원)을 보존" 문구가 §1 Summary 에 여전히 남아 있음. 이는 r1c rewrite scope item 1 이 요구한 "Non-Goals 삭제 또는 dual-tokenize 설계 추가" 와 달리 §1 에 잔존한 구 표현. 그러나 §1 Summary 는 introductory 요약 문단으로 전체 spec 을 대표하지 않으며, §4.1/§9.2 의 명시적 수정으로 self-contradiction 은 해소됨. §1 의 "보존" 문구는 §4.2 의 트레이드오프 절로 완전히 반박되고 있어, 독자가 양쪽을 읽으면 실제 동작이 명확히 전달됨. stylistic 잔존이나 substantive self-contradiction 은 아님.

Finding #2: 기존 KB backfill claim

critic 의 권장: eager backfill (V009 migration 또는 first-boot hook) 명시, 또는 lazy 명시 + release notes/AC 표현 일치.

  • §8.2: eager backfill 로 명시적 결단. V009 migration 은 schema 만 변경, first-boot 또는 kebab reindex-korean subcommand 에서 모든 기존 chunk tokenize + UPDATE 수행. 부분 완료 상태 search 동작 명시. backfill latency (~10,000 chunk 당 30-60s) 명시.
  • §9.1: "V009 migration 적용 + eager backfill 완료 후" 로 scope 명확화.
  • §12.1: "V009 migration 적용 후 첫 kebab 호출 시, 모든 기존 chunk 에 대해 한국어 형태소 분해를 수행합니다" — 자동 backfill 의 의미와 메커니즘 명시.
  • §9.3 verifier checklist: "Ingest 후 chunks.tokenized_korean_text 가 모든 한국어 chunk 에 채워짐" — "기존 chunk / 신규 ingest 분기" 가 §8.2 eager backfill 정책으로 단일화되어 모호성 해소.

Finding #3: unicode61 CJK tokenization 의 sub-morpheme 매칭 보장 부재

critic 의 권장: lindera-cli 실제 실행 결과 appendix 첨부 + AC §9.1 hit 보장과 cross-check.

  • Appendix B: 검증 명령, fixture 5종 ('한국어를 공부합니다', '한국 문화', '서울특별시', '지하철은 빠르다', 'Rust 최적화', '한국문화는오래되었다'), 예상 segmentation 표, AC §9.1 과의 일치성 분석이 포함됨.
  • 고유명사 정책 주의사항: Appendix B §9.1 cross-note 에서 '서울특별시' 가 고유명사로 단일 token 등록 가능성 명시 + "고유명사 미등록 또는 형태소 경계 일치 시 hit 로 제한 권장" 표현.
  • 제한 사항: Appendix B 의 segmentation 결과가 "prior knowledge 기반 예상" 이지 실제 lindera-cli 실행 출력이 아님. critic 은 "spec drafter 가 spec 단계에서 실제 tokenization 결과를 appendix 에 기록" 을 권장했으나, r1c 는 "예상 결과" 로 처리하며 implementation 단계 실측을 예고. 이는 partial resolution 이나, 핵심 우려 (AC §9.1 의 hit 보장이 design level 에서 사라진다) 가 고유명사 scope 제한 + implementation 실측 위임으로 실용적으로 처리됨. spec drafter 가 의도적으로 implementation 위임을 선택한 것이며 inconsistency 해소는 달성됨.

Finding #4: V007 CI diff-check 의 운명 미명시

critic 의 권장: rename / replace / delete 중 선택 + tests/fts.rs 편집 범위 명시.

  • §5.3: "rename 으로 V009 이동" 을 권장으로 명시. fts.rs 편집 범위 (V007 test → V009 rename, migration block 추출 대상 변경). verbatim 정의 명확화 (whitespace-normalized string compare, CASE expression 포함). Design §5.5 의 동일 갱신 범위 명시.

Finding #5: trigger race / ingest pipeline 순서

critic 의 권장: lindera tokenize + chunk INSERT 단일 transaction invariant 추가, tokenize 실패 fallback 정책 명시.

  • §6.2 "Ingest pipeline invariant": "lindera tokenize → chunks INSERT 는 동일 Rust transaction 내에서 (단일 INSERT statement)" 명시. chunks_ai trigger 가 NOT NULL branch 를 타는 invariant 보장. eager backfill 의 atomic transaction 명시. race condition (PRIMARY KEY 제약 강제) 명시.
  • §6.2 "tokenize_korean_morphological() 실패 처리": fallback (NULL + warning log) 정책 명시. error propagation 대안 미권장 이유 명시. graceful degradation 동작 명시.

Finding #6: storage / binary 비용 추정 의 evidence 부재

critic 의 권장: lindera-ko-dic size, binary delta, SQLite delta, ingest latency delta 실측 appendix 첨부.

  • §4.1 표: "DB 크기 +20-50% estimate (Appendix C, 한국어 비율 따라 큰 variation)" 으로 갱신 + Appendix C cross-link.
  • §10.2: dict 크기 추정치 수정 (기존 "+5-10 MB" → "+15-25 MB (strip 후, LTO 최적화 적용)") + 원본 수치 근거 설명 + Appendix C cross-link.
  • §10.3: Appendix C cross-link.
  • Appendix C: evidence sources (GitHub URL, crates.io URL), 추정 방법론, estimation bounds, implementation 실측 예고.
  • 제한 사항: Appendix C 의 수치가 "spike branch 불가능하므로 estimate" 임을 명시. 실제 measurement 아닌 web reference + prior knowledge 기반. 이는 critic 의 "측정값 첨부" 권장에 완전 부합하지 않으나, 현 spec 단계에서 실측이 어렵다는 맥락에서 투명하게 처리됨. Option A 선택 근거 (§4.1 비교표) 가 Appendix C 의 estimate bounds 로 보강됨.

Finding #7: search result ordering / eval baseline drift / corpus_revision

critic 의 권장: §11.3 wire content 변화 명시, §5.2 corpus_revision SQL 명시, §7.3 short_query_hint 운명 명시, surface cascade list 명시.

  • §5.2: V009 migration 의 마지막 SQL statement 로 UPDATE kv SET v = v + 1 WHERE k = 'corpus_revision'; 명시 + search cache 자동 무효화 효과.
  • §7.3: short_query_hint() 제거 이유 + 제거 범위 (grep -rn "short_query_hint") 명시.
  • §7.4 Surface cascade list: README.md / integrations/claude-code/kebab/SKILL.md / HANDOFF.md / docs/ARCHITECTURE.md 의 구체적 갱신 항목 명시. eval golden baseline 재생성 필요 + PR scope 명시.
  • §11.3: Wire schema shape 불변 + Wire content 변화 (hit ordering + snippet) 명시. BM25 score 분포 변동 이유 설명. eval golden baseline 재생성 필수 명시.

Finding #8: disable_korean_morphological config 노브

critic 의 권장: 노브 drop (Option A), build-time feature only (Option B), 보강 (Option C) 중 선택.

  • §6.3: Option A (노브 제거) 선택 + 이유 명시. "Config 노브 제거: disable_korean_morphological 는 추가하지 않음. Pre-1.0 단계이고, 한국어 지원은 core feature." 명시. 대안 (Option B, C) 미채택 이유도 기술.
  • eval baseline reproducibility 문제 (§8.4 언급 in critic) 는 노브 자체 제거로 근본 해소.

Finding #9: license + dict source 검증 evidence 부재

critic 의 권장: lindera 의 SPDX + Cargo.toml 인용, lindera-dict-ko-dic 의 SPDX + GitHub URL + upstream source, deny.toml allow-list 갱신 명시.

  • §10.1: "Evidence 는 Appendix D 참고" 로 cross-link.
  • Appendix D: lindera SPDX (MIT OR Apache-2.0) + GitHub URL + Cargo.toml license field 명시. lindera-dict-ko-dic SPDX (Apache-2.0) + GitHub URL + upstream (MeCab-ko-dic, KAIST 기반) 명시. deny.toml allow-list 갱신 절차 (cargo deny check 명령) 명시.
  • 제한 사항: "CC BY-SA 라이선스 없음 확인 필요, implementation 단계에서 fail-fast" 문구가 있어 완전한 확인은 implementation 으로 위임. critic 의 "Apache-2.0 만 dual-licensed 된 dict 가 아니면 reject 위험" 우려는 fail-fast 정책 명시로 처리됨.

New substantive findings (rewrite 도입)

rewrite 과정에서 새로 도입된 substantive issue 를 확인함.

1. §1 Summary 의 "기존 trigram 의 장점(영어 substring 매칭, 부분 매칭 지원)을 보존" 문구 잔존

§4.1/§4.2/§9.2/§12.1 이 모두 English substring 회귀 (Path A) 를 명시하고 있으므로, §1 의 이 문구는 사실과 반대. 그러나 §1 은 summary 단락이고, §4.2 트레이드오프 절이 바로 이 점을 부정하고 있어 spec 전체의 self-contradiction 수준은 아님. spec 을 순서대로 읽는 독자는 §4.2 에서 "영어 substring 매칭 회귀" 를 명확히 인지. risk: low.

2. §8.2 의 first-boot backfill 메커니즘 — Rust refinery migration 한계 미반영

§8.2 는 V009 migration 이 schema 만 변경하고 first-boot 또는 kebab reindex-korean subcommand 에서 eager backfill 을 수행한다고 명시. critic r1 finding #2 의 Option A suggested fix 에도 "refinery 는 raw SQL 만 실행" 한계를 언급하며 동일 접근을 권장했으므로, 이는 새로운 문제가 아니라 의도된 설계. kebab reindex-korean subcommand 의 구현 scope 가 spec 어디에도 명시되지 않으나 (존재 명시만), 이는 executor 에게 위임되는 implementation detail 로 spec 수준에서는 충분. risk: low.

3. Appendix A + 본문 Option 비교 section 의 중복

spec 본문 §4 뒤에 "## Appendix: 미평가 Option" 절과 "## Appendix A: 미평가 Option" 절이 중복으로 존재 (line 501-519 과 line 527-545 가 동일 내용). 이는 편집 artifact 로, design 또는 behavior surface 에 영향 없음. risk: none (cosmetic).

종합: 새로 도입된 substantive issue 없음. 위 3건 모두 low/none risk 로 NEEDS_REWRITE trigger 에 해당하지 않음.


Verdict rationale

critic R1 의 9개 finding (critical 3, major 6) 이 모두 r1c rewrite 에서 해소됨:

  • Finding #1: Path A (English substring 회귀 인정) 로 일관 갱신. §9.2 test rename + assertion 반전. §4.1 표 수정. §12.1 명시.
  • Finding #2: Eager backfill 결단 + §8.2/§9.1/§12.1 일관성. corpus_revision SQL + search cache 자동 무효화.
  • Finding #3: Appendix B segmentation evidence (prior knowledge 기반 예상) + AC §9.1 고유명사 scope 제한 명시. implementation 실측 위임 투명 처리.
  • Finding #4: §5.3 rename 선택 명시 + verbatim scope 명확화.
  • Finding #5: §6.2 transaction invariant + fallback 정책 명시.
  • Finding #6: Appendix C cost evidence (estimate bounds + web reference) + §4.1/§10.2/§10.3 cross-link.
  • Finding #7: §5.2 corpus_revision SQL + §7.3 hint 제거 + §7.4 surface cascade list + §11.3 wire content 변화 명시.
  • Finding #8: §6.3 노브 drop (Option A) 결단.
  • Finding #9: Appendix D SPDX + GitHub URL + deny.toml 절차 명시.

새 substantive finding 없음. 잔존 §1 Summary 의 "보존" 문구는 §4.2 로 즉시 반박되는 low-risk 표현이며, Appendix A 중복은 cosmetic artifact.

모든 critic finding resolved + 0 new substantive → ACCEPT.