opus PR-level final review (Approved with notes) 의 4 minor finding
mechanical 정정:
1. README.md — `kebab search` row 의 영어 substring 매칭 표현이
V007 시절 그대로였음. V009 의 whole-token 회귀 (substring → V002
동작) 를 정직히 명시 + vector/hybrid mode 권장 안내.
2. tasks/HOTFIXES.md — 2026-05-28 entry 의 file path 정정. lexical.rs
는 lindera 호출자가 아니라 build_match_string 의 MIN_QUERY_CHARS
3→2 갱신만; lindera helper 의 실제 owner 는 kebab-chunk/src/lib.rs.
ingest.rs 는 본 PR scope 외, eager backfill hook 위치는 kebab-app/
src/app.rs::App::open_with_config.
3. docs/wire-schema/v1/search_response.schema.json — `hint` field
description 이 V007 trigram 3-char minimum 시절 advisory 시그니처
그대로. v0.20.1 에서 helper retired + always-omit 사실 명시
(forward-compat 차원에서 field 만 schema 에 보존).
4. integrations/claude-code/kebab/SKILL.md — `hint` field 설명의
self-contradiction ("present only with trigram in edge cases" vs
"Korean 2-char now supported") 해소. retired + reuse 가능 명시.
PR-level reviewer recommendation: "Merge as-is — block 사유 아님 (모든
finding minor)". 본 commit 은 reviewer 의 옵션 1 (별 docs hotfix
commit) 채택.
Spec: docs/superpowers/specs/2026-05-28-v0.20.x-korean-morphological-tokenizer-spec.md
Plan: docs/superpowers/plans/2026-05-28-v0.20.x-korean-morphological-tokenizer-plan.md (PR-level finding follow-up)
V009 한국어 morphological tokenizer 의 사용자 visible surface 변경 +
release notes scope 를 5 docs 에 cascade.
- README.md: kebab search 명령 row 에 한국어 2자 query 지원 명시.
- integrations/claude-code/kebab/SKILL.md: V007 3-char hint 제거 +
V009 2자 한국어 query 지원 1줄.
- HANDOFF.md: C task status 완료 flip + v0.20.1 release notes scope
에 본 변경 추가 + 머지 후 발견 summary 행.
- docs/ARCHITECTURE.md: embedding upgrade (e5-small → e5-large),
lindera-ko-dic FTS5 한국어 지원, version notes 추가.
- tasks/HOTFIXES.md: 2026-05-28 entry — Bug #8 V009 해소, lindera-ko-dic
실제 crate name (spec deviation), cargo-deny deferred, Path A
영어 substring 회귀 명시.
Spec: tasks/p9/p9-9-v0.20.x-korean-morphological-tokenizer-spec.md §7.4
Plan: docs/superpowers/plans/2026-05-28-v0.20.x-korean-morphological-tokenizer-plan.md
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Two new wire schemas land as additive minor: ocr_stats.v1 (corpus-wide
aggregate — total_events, success_rate, p50/p90/p99/max_ms, by_engine,
top-10 by_doc by failure count) and ocr_failures.v1 (per-doc or
corpus-wide recent failures, with --doc-id + --limit). Both ship via
new CLI subcommands `kebab inspect ocr-stats` / `inspect ocr-failures`.
App gains four facade methods: inspect_ocr_stats /
inspect_ocr_failures plus their *_with_config companions — required by
CLAUDE.md "the facade rule" so `--config <path>` is honored. The CLI
dispatch arms thread cfg explicitly into the _with_config form.
Runtime introspection emit (WIRE_SCHEMAS in schema.rs) gains two
entries; the meta JSON Schema (schema.schema.json) is untouched
because its wire.schemas is pattern-based, not enum-based.
ingest_log::percentiles extended to (p50, p90, p99, max). p99 surfaces
only via inspect ocr-stats; IngestSummary (round 1) stays 3-percentile.
SKILL.md synced with the two new schemas (AC-13).
Closure r2 G2 (facade *_with_config pair) + G3 (runtime emit, not
meta schema file) + closure r1 F4 (p99) resolved.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
이전: schema.v1.models 가 parser_version / chunker_version 단일 값만 보고 →
multi-medium corpus (md + pdf + code Rust/Python + dockerfile + k8s + manifest)
의 version cascade audit 누락 risk.
이후: additive minor — Models struct 에 active_parsers + active_chunkers Vec<String>
추가. backward compat: 기존 단일 field 보존 (markdown default), 신규 array 는
optional (#[serde(default)] + JSON schema required 미포함).
source:
- kebab_store_sqlite::fetch_distinct_parser_versions() 가
documents.parser_version DISTINCT + ORDER BY 반환.
- fetch_distinct_chunker_versions() 가 chunks.chunker_version 동일 pattern.
- collect_models 가 매 schema 호출마다 재계산 (cache 없음 — R-3 자동 해결).
wire schema additive only — 메이저 bump 불필요. v0.20.1 minor 로 충분.
integrations/claude-code/kebab/SKILL.md 동기 갱신.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Why: kebab search --media code 가 v0.18.0 부터 functional support 됨
(MEDIA_KINDS 외 path 로 first-class 처리, schema.v1.media_breakdown.code
존재). 그러나 SearchArgs 의 clap doc-comment + SKILL.md line 57 의
value list 가 stale — `code` 누락. user 가 --help 만 보고 code 미지원이라
오해 가능.
Change: 2 surface 동기 — main.rs line 158-160 의 multi-line clap
doc-comment + integrations/claude-code/kebab/SKILL.md line 57.
Rust binary surface / wire schema 변경 0.
Out of scope (follow-up): crates/kebab-mcp/tools/search.rs:44,
crates/kebab-core/src/search.rs:32+52, crates/kebab-app/src/
ingest_progress.rs:69, crates/kebab-cli/tests/wire_schema_breakdowns.rs:35
도 동일 stale list 보유. spec ACCEPT (round 1c) 의 grep boundary
밖이므로 본 round 미포함.
Refs: docs/superpowers/specs/2026-05-27-v0.20-sub1-bugfix2-spec.md
§4.3 / §4.3a.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- HOTFIXES test 카운트 표기 정정: `9 신규 / 갱신 unit test` 의 산수
ambiguity → `9 unit test (8 갱신 + 1 신규) + 2 신규 통합 test = 11
total` 로 명시.
- SKILL.md (Claude Code integration) 의 search 절에 column scoping +
heading_path raw-mode escape hatch 안내 한 bullet 추가. 회차 1
의 follow-up suggestion 반영 — heading 검색 의도 agent 가 새
escape hatch `'heading_path : <token>'` 를 발견 가능.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- HOTFIXES: 새 2026-05-24 절 — v0.17.0 closure 영향 (한국어
lexical 3-gram, 영어 substring 변경, BM25 분포, 디스크 용량,
heading_path JSON 노이즈 관찰). 기존 2026-05-22 한국어 lexical
항목의 Status / Next step 을 closure 표현으로 갱신.
- HANDOFF: 머지 후 발견 deviation 절에 2026-05-24 entry +
기존 2026-05-22 항목을 closure cross-link 로 정리. P10
백로그 한국어 tokenizer 항목 ✅ v0.17.0 + "다음 task 후보"
follow-up 라인의 상태 갱신.
- README: 검색 명령 행에 trigram 동작 + hint + 디스크 용량 한 줄.
- SMOKE: 새 "한국어 trigram 검색 (v0.17.0)" 절 — 도그푸딩 query
시퀀스 (충돌은 raw / 해시 충돌 multi-token / Rust 충돌은
mixed / 충돌 2자 + stderr / --json hint 검증) + 영어 substring
동작 변경 안내.
- SKILL.md: search 절에 hint 필드 안내 한 줄 — agent 가
short query 케이스에서 같은 query 재시도 대신 사용자에게
surface 하도록.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous round-1 fix dropped the speculative cursor branch on
the truncated path, leaving a contradiction with the docs:
- snippet-only shrunk → cursor emitted (returned == k_effective)
- k-popped → cursor null (returned < k_effective)
But docs promised the opposite.
R2 resolution: emit cursor whenever more hits may be reachable
(either retriever filled the page OR budget popped hits — the
popped ones remain fetchable from offset+returned). Drop the
artificial "widen vs paginate" copy; truncated and next_cursor
are now independent signals — caller may do either or both.
Updates: app.rs::search_with_opts logic + SearchResponse doc +
schema description + SKILL.md two bullets + max_tokens=0 test
asserts cursor IS emitted on k-pop case.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- error_wire: StructuredError wrapper preserves ErrorV1 through
anyhow → classify pipeline. Adds downcast short-circuit so
cursor::decode's typed code = "stale_cursor" reaches the wire
instead of being string-formatted to code = "generic".
- app: search_with_opts now wraps cursor::decode error in
StructuredError instead of anyhow! string format.
- test: error_wire pins both negative (bare anyhow → not
stale_cursor) AND positive (StructuredError → stale_cursor)
invariants. CLI integration test runs end-to-end and asserts
error.v1.code on stderr.
- app: next_cursor only emitted on full-page (k-pop) path; drop
speculative emit on snippet-only truncation that would point at
a different page than the agent expected.
- cursor: differentiate malformed-base64 / malformed-payload /
revision-mismatch error messages; all keep code = stale_cursor.
- test: cursor_rejected fixture uses .expect() to fail loud on
cursor non-emission instead of silent skip.
- test: max_tokens=0 → 1-hit floor + truncated=true.
- docs: SKILL.md + schema description distinguish snippet-shrink
(widen) vs k-pop (paginate) truncated cases. HOTFIXES notes
--no-cache semantic shift (cached path + clear vs uncached path).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Repo-shipped skill previously framed CLI as primary surface with MCP
as a separate "recommended" alternative. Recipes still used CLI calls
even though MCP server has been the recommended surface since v0.3.1.
Now: MCP tool catalog (6 tools as `mcp__kebab__<name>`) leads, recipes
call MCP tools directly, CLI documented as fallback for hosts without
MCP. Generic wording preserved (no user-specific trigger keywords).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- kebab-app: add #[doc(hidden)] to ingest_stdin_with_config (CLAUDE.md
convention — all *_with_config functions should have this attribute;
fb-31's first impl missed it on the second facade fn).
- SKILL.md: "Since v0.4.0" → "Since v0.3.1" (MCP shipped in fb-30
release v0.3.1; the wrong version claim was introduced in fb-30 doc
sync and carried forward into fb-31).
- tools_call_ingest_file: add idempotency test (second call with same
content → unchanged=1, new=0). Spec called for two tests; first impl
shipped only the happy path.
Version bump 0.3.1 → 0.3.2 deferred to separate `chore/bump-v0.3.2` PR
mirroring fb-27 + fb-30 precedent (commits 73f5d73 / 5495d96).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- README 명령 표 에 `kebab mcp` 추가 + Claude Code MCP config 예시
- HANDOFF post-도그푸딩 항목 한 줄 (rmcp 1.6 + manual dispatch + error_wire promotion + ask/search spawn_blocking + capability flag flip 명시)
- CLAUDE.md facade 룰 의 UI crate 카테고리 에 `kebab-mcp` 추가
- integrations skill — MCP 사용 안내 (recommended over subprocess)
- design §10.2 MCP transport 절 신설
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- SKILL.md: `streaming_ingest` → `streaming_ask`, `multi_turn` → `rag_multi_turn` (capability name mismatch flagged in final review — agents following the example literal would read non-existent fields).
- HOTFIXES.md: add `not_indexed.details` to the interim wire shape deviations list — emit `{ expected, found }` only (spec literal `{ data_dir, expected, found }` not honored because NotIndexed signal carries one full path, not separate data_dir).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- README 명령 표 에 `kebab schema` 추가
- HANDOFF post-도그푸딩 항목 한 줄
- CLAUDE.md wire schema 절 schema.v1 / error.v1 추가
- integrations skill — schema 활용 안내 (additive)
- design §10.1 capability matrix subsection 신설
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add `integrations/claude-code/kebab/` — a Claude Code skill that calls
`kebab search --json` / `kebab ask --json` automatically when the user
asks an internal-context / runbook / wiki-lookup question. Install via
`cp -r integrations/claude-code/kebab ~/.claude/skills/` (or symlink for
in-place updates).
The shipped SKILL.md keeps its frontmatter `description` generic so the
trigger fires on any "internal / org-specific" cue — per-user keywords
(team / system / acronym) belong in a local override, not in the
repo-shipped frontmatter.
CLAUDE.md §Wire schema v1: add a paragraph documenting the
`integrations/<host>/` layout and the rule that a wire schema major bump
(v1→v2) updates each shipped integration in the same PR — same shape as
the version-cascade rule.
README.md §외부 AI 통합: replace the "~50줄 wrapper" prose with a direct
link to `integrations/claude-code/`, since the wrapper is now in-tree.