도그푸딩 피드백 3 건 (Library 컬럼 헤더 부재, PgUp/PgDn 페이지 스크롤,
모든 모드에서 항상 떠 있는 상태바 + 키 안내바 + 버전 정보) 을 단일
spec 으로 묶음.
설계 핵심:
- bottom 영역을 2 row 로 분할: 윗줄 = 상태바 (`kebab v0.1.0 │ pane │
doc_count │ 동적 상태`), 아랫줄 = 기존 footer_hints 그대로 이전.
- ingest progress 의 dedicated row 를 status bar 의 동적 영역으로 흡수
(시각적 source 단일화).
- Library `List` 위에 `format_doc_header` 헤더 row 추가 (TITLE / TAGS
/ UPDATED / CHUNKS, display-width 정렬, Role::Heading).
- Ask + Inspect 양쪽에 PgUp/PgDn (fixed step 10). Ask 는 j/k 와 동일
하게 follow_tail = false 로 freeze.
p9-fb-13 (footer 단행 row) + p9-fb-03 (ingest dedicated row) frozen
spec 들과 layout 충돌. frozen 텍스트는 그대로 두고 본 spec + 머지 후
HOTFIXES `2026-05-04 — p9-fb-24` 항목이 live source of truth.
Spec status `planned`. 다음 단계: writing-plans skill 로 implementation
plan 작성.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per-component README pages under docs/components/<group>/, grouped by
responsibility (12 groups). Each page carries 구조 + flow mermaid +
key-decision rationale consolidated from HOTFIXES + spec. Index page
hosts group-wiring diagram; ARCHITECTURE crate graph migrates from
ASCII to mermaid.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
도그푸딩 item 15 — TUI / 같은 process 안에서 동일 query 반복 시 SQLite
FTS + Lance + RRF 재계산이 매번 발생하던 비용 해소. in-process LRU
캐시 + 모노토닉 corpus_revision 카운터로 ingest commit 발생 시 모든
entry 자동 stale.
## 핵심 변경
- **SQLite V004 migration**: `kv (key TEXT PRIMARY KEY, value TEXT)
STRICT` + `corpus_revision = '0'` seed. 미래의 다른 scalar 도 같은
테이블에 들어갈 수 있는 generic shape.
- **`SqliteStore::corpus_revision()` / `bump_corpus_revision()`** —
`UPDATE ... CAST AS INTEGER + 1` atomic. INSERT-OR-IGNORE 도 함께
실행 (V004 seed 가 무슨 이유로 누락된 케이스 paranoid).
- **`kebab-app::ingest_with_config_cancellable`** — `new + updated > 0`
시 bump, no-op (skipped-only) reingest 는 cache 보존.
- **`App.search_cache: Option<Mutex<LruCache<SearchCacheKey, Vec<
SearchHit>>>>`** — `config.search.cache_capacity` (default 256, 0
비활성). `lru = "0.12"` workspace dep 추가.
- **`SearchCacheKey`** = `query_norm` (NFKC + trim + lowercase) +
`mode` + `k` + `snippet_chars` + `embedding_version` (vector/hybrid
만, lexical 은 빈 문자열) + `chunker_version` + `corpus_revision`
snapshot.
- **`App::search`** rewrite — cache 활성 시 lookup → miss 면 기존
`search_uncached` 호출 후 put. cache 비활성이거나 lock 실패면
straight-line.
- **`App::search_uncached`** (rename of pre-fb-19 `search` body) +
`search_uncached_with_config` facade — CLI `kebab search --no-cache`
로 진입.
- **`Config.search.cache_capacity: usize`** field, `#[serde(default)]`
로 기존 config 호환.
- **CLI `--no-cache`** flag — 디버깅용 (CLI 는 매 호출이 새 process
라 사실상 no-op 이지만 spec 명시 + 향후 long-lived process 호환).
- **frozen design §9 versioning** 표에 `corpus_revision` row 추가
(기존 `index_version` 라벨과 다른 차원: 라벨은 retrieval 형상,
corpus_revision 은 ingest commit ack).
## 테스트
- `kebab-store-sqlite` 신규 3 unit (fresh=0, monotonic bump, persist
across reopen)
- `kebab-app` 신규 4 integration (cached repeat 같은 hits, NFKC 정규화
로 case/whitespace collapse, --no-cache parity, first ingest bumps
corpus_revision)
- 워크스페이스 전체 `cargo test --workspace --no-fail-fast -j 1` exit 0
- `cargo clippy --workspace --all-targets -- -D warnings` clean
## 문서
- README `kebab search` 행: 캐시 동작 + `--no-cache` 안내 + corpus_
revision 무효화 메커니즘
- docs/SMOKE.md `[search]` 절에 `cache_capacity` 라인 추가
- HANDOFF: 2026-05-03 entry
- spec status planned → in_progress
## Out of scope
- patch-and-merge incremental (RRF 정규화 전체 hit set 기준이라 어려움)
- SQLite 영속 cache (P+)
- 다른 process 간 cache 공유 (in-process 만 — corpus_revision 이
cross-process 무효화는 O(1))
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
회차 1 actionable 2건 반영.
- §3.8 RefusalReason enum 에 LlmStreamAborted variant 추가 + doc
comment (RAG retrieval 정상, model generation 단계에서만 중단).
spec PR self-contained 원칙 — impl PR 이 spec 변경 없이 진행
가능.
- Multi-turn behaviour 절 끝 빈 줄 2 → 1 + RefusalReason 정의
cross-link 한 줄 추가.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
도그푸딩 후 추가된 ask multi-turn (꼬리 물기) surface 를 frozen design
+ wire schema 에 명시. p9-fb-15 (RAG core) + p9-fb-16 (TUI UI) +
p9-fb-17 (V004 chat sessions) + p9-fb-18 (CLI session/repl) 의 spec
PR — impl PR 들이 이어진다.
변경:
- §2.3 Answer wire schema: conversation_id (String?) + turn_index
(u32?) 두 optional 필드. 기존 single-shot 소비자 (외부 wrapper)
영향 없음 — 두 필드 모두 optional.
- §3.8 RAG types:
- Answer struct 에 conversation_id / turn_index field 추가.
- Turn struct 신설 (history 가 prompt 에 들어갈 때 한 turn).
- §3.8 \"Multi-turn behaviour\" 신설 절:
- kebab-rag::ask vs ask_with_history 두 entry.
- prompt 빌드 priority: system+question (필수) → retrieved chunks
(k 줄여 fit) → history (newest 우선, oldest drop).
- retrieval query expansion (직전 answer 첫 200자 concat).
- Aborted vs Completed semantics — ask 는 single-shot 이라 cancel
시 partial token + grounded=false + LlmStreamAborted refusal
(variant 추가는 p9-fb-15 impl 가 함께).
- docs/wire-schema/v1/answer.schema.json: 두 필드 추가 +
created_at 에 format: date-time (sibling ingest_progress.v1 와
일관).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- §10 long-running 절 끝 빈 줄 3 → 1 (다른 절 사이 일관)
- wire schema + §2.4a 예제 JSON: kind_result → result (top-level
kind 와의 모호성 제거; ingest_report.v1.items[].kind 와 짝)
- wire schema 의 ts 필드: format: \"date-time\" 추가 (RFC 3339
자동 검증, wrapper 가 다른 format emit 시 즉시 잡힘)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
도그푸딩 후 추가된 long-running 작업 진행 표시 + cancel 정책을 frozen
design 에 명시. p9-fb-01/02/03 (ingest progress callback / CLI display
/ TUI background) 의 spec PR — impl PR 들이 이어진다.
변경:
- docs/wire-schema/v1/ingest_progress.schema.json (신규):
line-delimited streaming event schema. discriminated by `kind`
(scan_started → scan_completed → asset_started → asset_finished* →
embed_batch_* → completed | aborted). 마지막 줄은 기존
ingest_report.v1 그대로 (외부 wrapper backward-compat).
- 2026-04-27-kebab-final-form-design.md §2.4a (신규):
IngestProgressEvent 절. 이벤트 ordering / aborted 의 idempotency /
CLI 의 stderr vs stdout 분리 / TUI · desktop 의 in-memory 소비.
- 2026-04-27-kebab-final-form-design.md §10:
long-running 작업 (ingest, future eval run, RAG streaming, embed
batch) 의 두 invariant — progress 의 단일 source / cooperative
cancel + step boundary. trait (§7.2) 시그니처는 무영향 — facade
hidden parameter 로 추가.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR #1 review left a design-debt note: ParsedBlock landing in kb-core would
(a) force every crate to recompile on parser-internal changes, and
(b) cause namespace pollution when P6/P7/P8 parsers add their own variants.
Resolution: a new thin crate kb-parse-types sits between kb-core and parsers.
Owns ParsedBlock + ParsedPayload + Warning + forward-refs for image/pdf/audio
parser intermediates. Depends on kb-core only (for SourceSpan / Inline).
Updates:
- design §3.7b: add new section defining kb-parse-types
- design §8: add kb-parse-types to module-boundary diagram + forbidden list
- design §3.4 Inline stays in kb-core; kb-parse-types references it (no duplication)
- p0-1 skeleton: workspace + Cargo deps + public surface block
- p1-3 parse-md-blocks: outputs Vec<kb_parse_types::ParsedBlock> directly
- p1-4 normalize: Allowed gains kb-parse-types, drops cross-coupling note
- INDEX + phase-0 epic: list kb-parse-types in P0 deliverables