Files
kebab/HANDOFF.md
altair823 70507e94ca docs(handoff): logging round 2 closed (PR #190 merged) + v0.20.1 release notes scope 갱신
PR #190 (2026-05-28 commit 7bbdc89a) merge 후:
- "Logging feature future enhancements" section →  closed (4 enhancement 모두 PR #190 에서 ship).
- G (v0.20.1 release) section 의 release notes scope 갱신 — V008 migration + pdf_ocr_events + CLI inspect + retention 추가.

다음 작업 priorities 그대로 C → B → A → G.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 08:15:07 +00:00

51 KiB
Raw Blame History

HANDOFF — 진척도

새 conversation / 다른 사람이 이어받을 때 "지금 어디까지 됐고 다음에 뭘 할지" 의 단일 출처. 사용자 사용법은 README.md, 아키텍처는 docs/ARCHITECTURE.md, per-component 진행은 tasks/INDEX.md, 머지 후 발견된 버그는 tasks/HOTFIXES.md. 이 파일은 "phase 단위 진척" + "다음 task 후보" 만 담는다.

한 줄 요약

P0P5 + P6 + P7 + P9-1/2/3/4 (Library / Search / Ask / Inspect) + P10 전체 머지 완료 (현재 v0.18.0). kebab ingest 가 markdown / image / PDF / 소스코드 (Rust / Python / TS / JS / Go / Java / Kotlin / C / C++) / Tier 2 리소스 파일 (yaml/k8s / dockerfile / toml / json / xml / groovy / go-mod) + Tier 3 paragraph fallback (shell / 비-k8s YAML / AST 실패 케이스) 처리. kebab search / kebab ask 가 매체 가로질러 결과 + page / code citation 반환. kebab tui 가 4 패널 (Library + Search + Ask + Inspect) 제공. v0.17.0 cut (2026-05-24): 한국어 trigram FTS5 tokenizer (PR #159) + C typedef alias unit (PR #160) + code_lang_chunk_breakdown additive (PR #161). v0.17.1 cut (2026-05-25): 확장 도그푸딩 후 [models.llm] request_timeout_secs config 노브 (PR #162) + sudo 없이 ollama 설치 + kebab ask --stream UX 권장 docs (PR #163). v0.17.2 cut (2026-05-25): v0.17.1 post-dogfood polish — [image.ocr] request_timeout_secs 별 노브 (PR #164, v0.17.1 미진행 closure) + heading_path FTS5 column filter 로 text-only 매칭 + raw-mode escape hatch (PR #165, 2026-05-24 v0.17.0 trigram entry 의 JSON 노이즈 closure). v0.18.0 cut (2026-05-26): fb-41 multi-hop RAG + NLI verification ship (PR #176-180) — kebab ask --multi-hop 의 decompose → decide → synthesize loop + mDeBERTa-v3 XNLI ONNX post-synthesize entailment 검사. dogfood S7 caffeine hallucination 의 silent LLM-self-judge ceiling 해결 (nli_score 0.0035 graceful refuse). 추가 chore: workspace-wide cleanup + post-PR9 refactor (PR #181) — clippy::pedantic baseline + H1 config wiring + 9 new tests. 자세한 영향은 v0.17.0 release notes + v0.17.1 release notes + v0.17.2 release notes + v0.18.0 release notes. 구조적으로 남은 component 는 P9-5 (desktop tauri) 하나뿐, P8 (audio) 는 사용자 보류.

Phase 로드맵

Phase 내용 핵심 산출 crate 선행 상태
P0 Workspace 뼈대 + 도메인 계약 + ID recipe kebab-core, kebab-parse-types, kebab-config, kebab-app, kebab-cli 완료
P1 Markdown ingestion (walk → parse → chunk → SQLite) kebab-source-fs, kebab-parse-md, kebab-normalize, kebab-chunk, kebab-store-sqlite P0 완료
P2 SQLite FTS5 lexical 검색 + citation kebab-search (lexical) P1 완료
P3 Local embedding + LanceDB + hybrid (RRF) + kebab-app wiring kebab-embed, kebab-embed-local, kebab-store-vector, kebab-search P2 완료
P4 Local LLM + RAG + grounded answer kebab-llm, kebab-llm-local, kebab-rag P3 완료
P5 Golden query / regression eval kebab-eval P4 완료
P6 이미지 ingestion (OCR + caption) kebab-parse-image P5 완료 (4/4 component, OCR/caption Ollama-vision)
P7 PDF text + page citation + scanned OCR (v0.20.0 sub-item 1) kebab-parse-pdf + kebab-app::pdf_ocr_apply P5 + P6 완료 (3/3 component, page-level chunker + ingest wiring + post-extract OCR enrichment via qwen2.5vl:3b vision LLM)
P8 음성 transcription + timestamp citation kebab-parse-audio P5 ⏸ 보류 (whisper-rs 시스템 dep brainstorm 필요)
P9 TUI + desktop app kebab-tui, kebab-desktop P5 🟡 진행 (4/5 component — P9-1/2/3/4 완료 [Library / Search / Ask / Inspect], P9-5 desktop 예정 · 도그푸딩 피드백 20/20 )
P10 code ingest framework kebab-parse-code P5 🟡 진행 중 — 1A-1 (wire schema + parse-code skeleton + filter flags), 1A-2 (Rust AST chunker, code-rust-ast-v1 — v0.7.0), 1B (Python/TS/JS AST chunkers — v0.8.0 이후), 1C-Go (Go AST chunker, code-go-ast-v1 — v0.12.0), 1C-JavaKotlin (Java + Kotlin AST chunkers, code-java-ast-v1 / code-kotlin-ast-v1 — v0.13.0), 2 (Tier 2 resource-aware: yaml/k8s + dockerfile + manifest, k8s-manifest-resource-v1 / dockerfile-file-v1 / manifest-file-v1 — v0.14.0), 3 (Tier 3 paragraph fallback: code-text-paragraph-v1 — v0.15.0), 1D (C + C++ AST chunkers, code-c-ast-v1 + code-cpp-ast-v1 — v0.16.0)

P0P5 직렬. P6P9 P5 이후 병렬 가능.

Component 카운트

총 33 component task — spec 시점 31 개 + 후속 wiring task 3 (P3-5 / P6-4 / P7-3) 가 머지 시점에 추가됨. v0.18.0 cut 시점에 fb-41 multi-hop RAG + NLI verification (PR-9 5 sub-PRs) 가 P9 추가 component 로 ship — kebab-nli 신규 crate (mDeBERTa-v3 XNLI ONNX verifier) + kebab-rag::ask_multi_hop (decompose/decide/synthesize loop + step 8.5 NLI hook). per-component 진행 + status 는 tasks/INDEX.md.

머지 후 발견된 버그 / 결정 (요약)

머지 후 발견된 모든 deviation / hotfix 의 dated 로그는 tasks/HOTFIXES.md. 본 요약은 "누군가가 인수받을 때 알아두면 시간을 많이 절약하는" 항목만:

  • v0.20 sub-item 1 (scanned PDF OCR via qwen2.5vl:3b): post-extract enrichment pattern (kebab-app::pdf_ocr_apply, H-1 resolution), DCTDecode-only v1 scope (FlateDecode/CCITTFax page 는 warning + skip), parser_version "pdf-text-v1" 보존 + force-reingest UX 명문 (H-4).

  • 2026-05-26 kebab-normalize + kebab-parse-types 흡수 (24 → 22 crates, design §3.7b 재작성) — v0.19.0 cut. 4 parser 중 markdown 한 갈래만 lift 를 경유하는 reality 가 design §3.7b 의 fan-in ≥ 2 가정과 diverge → thin layer (kebab-parse-types) + kebab-normalize 두 crate 가 kebab-parse-md 로 흡수. 5 사용 type + 3 forward-declared struct 모두 kebab-parse-md::{types,normalize} module 의 pub re-export 로 보존. wire / surface impact = 0 (CLI / TUI / MCP / --json / config / XDG / parser_version 모두 unchanged). 자세한 내용: tasks/HOTFIXES.md (2026-05-26 design deviation entry).

  • 2026-05-26 v0.18.0 fb-41 multi-hop RAG + NLI verification ship (PR #176-180) + post-PR9 cleanup (PR #181) — pre-v0.18.0 dogfood (/build/cache/dogfood-v018/, 33 assets / 205 chunks, gemma3:4b CPU only / 16 GB RAM) 에서 발견된 S7 caffeine hallucination 의 root cause = LLM-self-judge ceiling (synthesize 가 chunks 와 무관한 Adam optimizer gradient 식을 silent emit, self-judge 가 reject 못함). 학계 표준 (Self-RAG, CRAG, Auto-GDA, MedTrust-RAG) 결론 = deterministic post-synthesis verification. mDeBERTa-v3 XNLI ONNX (280 MB, Xenova HF) 가 (packed_chunks, answer) entailment 검사 — [rag] nli_threshold > 0 (default 0.0 = disabled, production 권장 0.5) 일 때 활성. dogfood retest 측정 — S7 PR-8 baseline grounded=true + Adam hallucination → PR-9 nli_verification_failed, nli_score 0.0035. wire additive minor — answer.v1.verification field + refusal_reasonnli_verification_failed / nli_model_unavailable 추가, pre-v0.18 reader 무영향. 5 sub-PR 시퀀스 + cleanup PR (clippy::pedantic baseline + 의도적 30+ allow + H1 [models.nli].model config wiring + 9 new tests). post-refactor retest = PR-9d byte-identical (deterministic 확인). 자세한 내용: tasks/HOTFIXES.md (2026-05-25 fb-41 PR-9 closure entry + S3 follow-up).

  • 2026-05-25 v0.17.2 post-v0.17.1 polish (PR #164 + #165) — v0.17.1 의 두 follow-up closure. (1) [image.ocr] request_timeout_secs 별 노브 — crates/kebab-parse-image/src/ocr.rs::REQUEST_TIMEOUT hard 300s 제거, LLM 쪽 패턴 (PR #162) 을 OCR 어댑터에 동일 적용. 사용자 결정으로 별 노브 분리 (OCR vs LLM 의 cold start 패턴이 달라 독립 조절). v0.17.1 미진행 항목 closure. (2) chunks_ftsheading_path 컬럼이 JSON 표기 + path 세그먼트 까지 trigram 색인 → query false positive 가능 문제 closure. lexical.rs::build_match_string 가 non-raw 분기 결과를 text : (<expr>) 로 wrap — heading 색인 V007 verbatim 유지, 매칭만 text 한정. 사용자가 명시 heading 검색 하려면 raw mode 'heading_path : <token>' escape hatch (SKILL.md 갱신). 둘 다 additive (옛 config 호환) / re-ingest 불필요. 자세한 내용: tasks/HOTFIXES.md (2026-05-25 v0.17.2 두 entry).

  • 2026-05-25 v0.17.1 post-dogfood (PR #162 + #163) — 확장 도그푸딩 (16 GB CPU only, gemma4:e4b 시도) 에서 발견된 두 follow-up 한 묶음. (1) crates/kebab-llm-local/src/ollama.rs::REQUEST_TIMEOUT hard 300s → [models.llm] request_timeout_secs config + env override (additive, default 300, =0 은 disable 아닌 "즉시 timeout" 이라 doc 명시). (2) README + SMOKE 에 sudo / systemd 없이 ollama 설치 + ≤4B Q4 권장 모델 + kebab ask --stream UX 권장 docs. additive only — 옛 config / wire 호환. 자세한 내용: tasks/HOTFIXES.md (2026-05-25).

  • 2026-05-24 v0.17.0 PR-C code_lang_chunk_breakdown additive (closure of 2026-05-22 LOW)schema.v1.stats 에 chunk 수 집계 신규 키. 기존 code_lang_breakdown (doc count) 와 sister. 또 기존 두 필드 JSON schema description 의 "chunk count" 오기재 → "doc count" 로 정정. wire additive — schema_version bump 불필요. 자세한 내용: tasks/HOTFIXES.md (2026-05-24 PR-C).

  • 2026-05-24 v0.17.0 PR-B C typedef alias unit (closure of 2026-05-21)kebab-parse-code::c::extract_blockstype_definition 분기로 inner anonymous struct/enum/union → declarator 의 typedef alias 이름으로 synthetic unit 방출. PARSER_VERSION code-c-v1code-c-v2 bump + 같은-asset/다른-doc_id 케이스용 purge_workspace_path_for_parser_bump cascade (stale_chunk_ids_for_workspace_path_except_doc_id + purge_document_at_workspace_path_except_doc_id helper 신규). 사용자 작업 불필요 (다음 ingest 가 자동 재처리). 자세한 내용: tasks/HOTFIXES.md (2026-05-24 PR-B).

  • 2026-05-24 v0.17.0 PR-A 한국어 trigram tokenizer 채택 (closure of 2026-05-22 한국어 lexical)chunks_fts 가 FTS5 unicode61trigram 으로 V007 migration (자동 backfill, re-ingest 불필요). lexical.rs::build_match_string trigram-aware 재설계 — multi-token 한국어 query (해시 충돌) 가 whole-phrase 후보로 hit, 한영 혼합 (Rust 충돌은) 도 OR-combined. 2자 이하 query 는 0-hit + CLI/TUI/wire hint 안내. 영어 lexical 도 substring 매칭으로 바뀜 (recall ↑ / 단어 경계 ↓). kebab.sqlite 크기 ~2-5배 증가 (trigram index). 자세한 내용: tasks/HOTFIXES.md (2026-05-24).

  • 2026-05-22 P10 종합 도그푸딩 round 2 (한국어 lexical 검색 한계)kebab search --mode lexical 의 한국어 query 가 FTS5 unicode61 토크나이저에서 거의 0 hit (어절 단위 토큰화 → 부분 매칭 불가). 기본 hybrid 모드는 multilingual-e5-small vector 가 carry 해 한국어 검색 정상. closure: 위 2026-05-24 v0.17.0 entry.

  • 2026-05-20 P10-1B (Rust 1A symbol path 비일관 + expression-level 함수 미방출) — (a) Rust code-rust-ast-v1 은 file-scope nesting 만 (workspace path prefix 없음), 1B 의 Python/TypeScript/JavaScript 는 workspace 경로 → module path prefix 사용 (비일관 수용, retrofit = chunker_version bump + reindex 필요, 사용자 명시 요청까지 보류); (b) TS/JS 의 const foo = () => {...} 같은 expression-level 함수는 <top-level> glue 로 처리됨 (declaration-level 단위만 1B 1차 범위). 자세한 내용: tasks/HOTFIXES.md (2026-05-20) 두 항목.

  • 2026-05-19 P10-1A-2 (code_rust_ast_v1.rs + SourceType)AST_CHUNK_MAX_LINES 상수가 IngestCodeCfg.ast_chunk_max_lines 를 읽지 않고 모듈 상수 200 고정 (Chunker trait 이 per-medium config 미노출); SourceType::Code variant 부재로 code 파일이 SourceType::Note 로 분류됨 — 두 항목 모두 tasks/HOTFIXES.md (2026-05-19) 에 기록.

  • 2026-05-07 fb-26 (progress.rs)Aborted unconditional writeln (TTY duplicate) + Completed TTY no summary fixed; KEBAB_PROGRESS=plain env + quiet suppression added

  • 2026-05-07 fb-28 (main.rs)--readonly (KEBAB_READONLY) blocks Ingest/IngestFile/IngestStdin/Reset; --quiet suppresses progress stderr; error.v1 code: "readonly_mode"

  • 2026-05-07 macOS XDG path collision (config 사라지는 버그)dirs crate 가 macOS 에서 config_dir()data_dir() 둘 다 ~/Library/Application Support/ 반환 → reset --data-only 가 config 파일까지 삭제. Fix: ~/.config, ~/.local/share, ~/.cache 직접 사용. 새 경로: config ~/.config/kebab/, data ~/.local/share/kebab/, cache ~/.cache/kebab/. Config::load(None) 이 macOS legacy path 에서 자동 마이그레이션. 자세한 내용: tasks/HOTFIXES.md.

  • 2026-05-07 P9 post-도그푸딩 (p9-fb-31)kebab ingest-file <path> + kebab ingest-stdin --title <T> 두 신규 subcommand + MCP tool ingest_file / ingest_stdin (4 → 6 tool). agent 가 fetch 한 web markdown / 외부 file 을 KB 에 즉시 저장. workspace 외부 file 은 <workspace.root>/_external/<blake3-12>.<ext> 로 copy (deterministic 명명 → idempotent). _external/ 디렉토리 첫 생성 시 .kebabignore 자동 append (walk 무한 루프 방지). stdin 은 markdown 전용 + flag (--title, --source-uri) → frontmatter 자동 prepend. .kebabignore 매치 시 stderr warn 후 진행 (explicit ingest = bypass intent). fb-30 의 v1 read-only MCP 정책 변경 — 첫 mutation tool 도입. spec: tasks/p9/p9-fb-31-single-file-stdin-ingest.md. design: docs/superpowers/specs/2026-05-07-p9-fb-31-single-file-stdin-ingest-design.md.

  • 2026-05-07 P9 post-도그푸딩 (p9-fb-30)kebab mcp 신규 subcommand + new crate kebab-mcp (lib only) — stdio JSON-RPC server. 4 read-only tool (search / ask / schema / doctor) 가 kebab-app facade 위에 build. rmcp 1.6 SDK 채택, manual tools/list + tools/call dispatch (rmcp 의 #[tool_router] 매크로 대신). error_classify 모듈을 kebab-clikebab-app::error_wire 로 promotion (UI crate 끼리 import 회피, facade 룰 준수). ErrorV1schema_version: String 필드 추가 — kebab-mcp 의 직접 serialize 경로에서도 wire 정합. KebabAppState(Config, Option<PathBuf>) carry — doctor tool 의 path-aware behavior 위해. ask + search arm 의 tokio::task::spawn_blocking wrap — OllamaLanguageModel 의 reqwest blocking client 가 async 안에서 panic 회피. capability flag mcp_server falsetrue. agent integration MVP 완성 — Claude Code / Cursor / OpenAI Agents 등 host-agnostic 사용 가능. spec: tasks/p9/p9-fb-30-mcp-server.md. design: docs/superpowers/specs/2026-05-07-p9-fb-30-mcp-server-design.md.

  • P3-5 / P4-3 --config 누락kebab-cli--config <path> 를 honor 하려면 kebab_app::*_with_config companion 을 호출해야 함. 두 번 같은 모양으로 회귀했음.

  • P6-2 OCR 기본 엔진 — spec literal 의 Tesseract 가 시스템 dep 부담으로 거부됨, Ollama vision LM 으로 대체. OcrEngine trait 그대로라 future swap 가능.

  • P6-3 captionGenerateRequest.images 필드를 kebab-core::LanguageModel trait 에 신설. 기존 caller 모두 images: Vec::new() 로 마이그레이션.

  • P7-2 chunk_id 충돌 — pdf-page-v1 가 한 페이지 여러 chunk 분할 → 같은 block_ids 충돌. per-chunk policy_hash#c{char_start} 변형 으로 회피.

  • P7-3 storage UNIQUE bugassets.workspace_path UNIQUE + upsert_asset_rowON CONFLICT(asset_id) gap 으로 byte 변경 re-ingest 실패. purge_orphan_at_workspace_path helper 추가, follow-up PR 으로 vector store orphan cleanup 까지 닫음 (VectorStore::delete_by_chunk_ids).

  • P9-1 ratatui 0.28 — spec literal 의 render_library<B: Backend> generic 이 ratatui 0.28 의 backend-agnostic Frame 과 어긋나 있어 제거. 테스트 seam App::populate_library_for_testing (#[doc(hidden)]) 추가.

  • P9-2 jump_to_citation workspace_root — spec literal 의 jump_to_citation(citation, editor_env) 가 workspace_root 인자 누락. citation.path 가 workspace 상대라 editor 호출 시 절대 경로 필요 → workspace_root: &Path 인자 추가. 동일하게 render_search<B: Backend> generic 도 P9-1 과 같은 사유로 제거.

  • P9-3 e/j/k 키 의 "input empty" 분기 — spec 의 e=toggle explain / j=k=scroll 이 typing 과 충돌 ("explain" / "javascript" 같은 단어 입력 깨짐). input 이 비어 있을 때만 command 키로 동작 — vim "command vs insert" 컨벤션 변형. 사용자가 텍스트 입력 시 모든 알파벳 정상 통과.

  • P9-4 enter_inspect helper + Search i — spec 의 진입 경로 (Library Enter → Doc inspect, Search i → Chunk inspect) 를 한 helper 로 묶음. InspectTarget enum (Doc(DocumentId) | Chunk(ChunkId)), return_to: Pane 가 Esc 시 원래 pane 으로 복귀. c 키가 모든 section (metadata / provenance / blocks / spans / text / embeddings) 일괄 collapse/expand — spec 의 "focus 기반 selective collapse" 는 v1 단순화.

  • 2026-05-02 P9 도그푸딩 후속 (p9-fb-06)kebab reset --all|--data-only|--vector-only|--config-only [--yes] 추가. TTY 가 아니면 --yes 필수 (silent destruction 금지). --vector-only 가 SQLite embedding_records 도 함께 truncate (off-disk Lance dir 만 wipe 시 orphan 방지). 도그푸딩 막힘 강도 1위 (수동 4 경로 rm -rf 부담) 해소. spec: tasks/p9/p9-fb-06-data-reset-command.md, plan: docs/superpowers/plans/2026-05-02-p9-fb-06-reset-command.md.

  • 2026-05-02 P9 도그푸딩 후속 (spec PR #51 + p9-fb-01 + p9-fb-02)kebab ingest 진행 표시 도입. frozen design §2.4a 신설 (wire schema ingest_progress.v1 line-delimited streaming) + §10 의 long-running 작업 절 추가. kebab-app::ingest_with_config_progress(.., progress: Option<Sender<IngestEvent>>) facade 추가, 기존 _with_configprogress=None forwarding wrapper. CLI 가 indicatif TTY 진행 바 (stderr) / non-TTY 한 줄씩 / --json 모드는 line-delimited stdout. p9-fb-03 (TUI background worker) + p9-fb-04 (cancel) 가 같은 stream 위에 build.

  • 2026-05-02 P9 도그푸딩 후속 (p9-fb-03) — TUI 의 background ingest worker. Library 의 r 키가 kebab_app::ingest_with_config_progress 를 spawned thread 에서 호출, run loop 가 매 frame 마다 progress channel drain → 화면 하단 status bar 1 줄 갱신. terminal event (Completed/Aborted) 후 3 초 final 라인 hold + 자동 hide + Library auto-refresh. spec: tasks/p9/p9-fb-03-tui-ingest-background.md. (cancel slot 은 p9-fb-04 가 추가하는 형태로 단일화 — 회차 1 review 결과.)

  • 2026-05-02 P9 도그푸딩 후속 (p9-fb-04) — ingest cooperative cancellation. kebab-app::ingest_with_config_cancellable(.., cancel: Option<Arc<AtomicBool>>) facade 추가, 기존 _progresscancel=None forwarding. asset loop iter 시작 boundary 마다 cancel poll → true 면 break + IngestEvent::Aborted { partial_counts } + Ok(IngestReport) 정상 반환 (Err 아님). 부분 commit 보존, 다음 ingest 가 idempotent 재개. CLI Ctrl-C SIGINT handler (ctrlc crate) — 1회: cancel, 2회: hard exit (130). TUI Esc / Ctrl-C 가 cancel signal (in-flight 시), 그 외에는 quit. IngestStatecancel: Arc<AtomicBool> field 추가. spec: tasks/p9/p9-fb-04-ingest-cancellation.md.

  • 2026-05-02 P9 도그푸딩 후속 (spec PR #59 + p9-fb-15) — RAG multi-turn 도입. frozen design §3.8 갱신 — Answerconversation_id / turn_index optional field, 신규 Turn struct, RefusalReason::LlmStreamAborted variant. kebab-rag::AskOptshistory: Vec<Turn> / conversation_id / turn_index 3 field 추가, 기존 caller 는 Vec::new() / None (single-shot 동작 동일). RagPipeline::ask_with_history(query, history, conversation_id, turn_index, opts) helper. prompt 빌드: [이전 대화] 블록을 user prompt 위에 prepend, newest-first, char budget (cfg.rag.max_context_tokens * 4) 안에서 oldest 부터 drop. retrieval query expansion: 직전 answer 첫 200 자 concat. wire schema answer.v1 에 두 필드 + format: date-time 추가. p9-fb-16 (TUI conversation UI) + p9-fb-17/18 (V004 storage + CLI session) 가 같은 facade 위에 build. spec: tasks/p9/p9-fb-15-rag-multi-turn-core.md.

  • 2026-05-02 P9 도그푸딩 후속 (p9-fb-16) — TUI Ask conversation UI. AskStateturns: Vec<Turn> + current_question + conversation_id + last_answer 로 재설계. answer area 가 transcript (Q1/A1, Q2/A2, ...) 로 갈음, 매 Enter 가 이전 turns 를 history 로 worker 에 전달 (ask_with_history). conversation_id 는 첫 submit 시 timestamp-based 자동 생성 (conv_<unix_nanos_hex>). Ctrl-L 가 turns + conversation_id 초기화 (in-flight worker 는 그대로 finish, 결과는 새 conversation 의 stale turn 으로 silently 폐기). spec: tasks/p9/p9-fb-16-tui-ask-conversation.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-20)kebab ask 의 CLI citation block. 답변 출력 후 근거: 절 — [N] <full path>#<fragment> (score=<s>) 한 줄씩. --show-citations (default ON) / --hide-citations (pipe 시 답변 본문만) flag. --json 모드는 무영향 (citations 가 항상 wire payload 에 포함). spec p9-fb-20 의 "TUI citation pane + jump" 부분은 P9-3 의 기존 render_citations_or_explain 가 일부 cover — 추가 기능 (turn 별 fold + Enter/o jump + i inspect) 은 후속 task 로 미룸 (사용자 도그푸딩 priority 5위 의 핵심 = full path 가독성 = CLI block 으로 충족). spec: tasks/p9/p9-fb-20-citation-surface.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-07) — Markdown title fallback chain. kebab-normalize::derive_title(frontmatter_title, &[Block], file_stem) — 1) frontmatter title → 2) 첫 H1 → 3) 첫 H2 → 4) 첫 paragraph 80 chars → 5) 파일 stem (모든 단계 NFC 정규화, 빈 문자열 절대 반환 안 함, 마지막 sentinel "untitled"). build_canonical_document 가 lift 후 helper 호출. parser_version 상수 pulldown-cmark-0.xmd-frontmatter-v2 bump — 기존 doc 은 doc_id 가 갱신되므로 다음 ingest 가 자동 재처리 (idempotent upsert, design §9 cascade). spec: tasks/p9/p9-fb-07-md-title-fallback.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-09) — TUI external editor return restore. Search g 키 (citation jump) 후 TUI 화면이 깨지는 버그 수정. kebab-tui::editor::with_external_program(&mut TuiTerminal, Command) helper 가 suspend (LeaveAlternateScreen + Show cursor + disable_raw_mode) → spawn → restore (enable_raw_mode + EnterAlternateScreen + Hide cursor + terminal.clear()) 시퀀스를 RAII guard 로 atomic 하게 묶음. App.pending_editor: Option<EditorRequest> + App.force_redraw: bool 추가 — 키 핸들러는 EditorRequest enqueue 만, 실제 spawn 은 run loop 가 TuiTerminal 핸들 들고 처리. 후속 task (p9-fb-20 의 citation jump 등) 가 같은 helper 위에 build. spec: tasks/p9/p9-fb-09-tui-editor-restore.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-14) — TUI color theme module. kebab-tui::theme::{Theme, Role, Palette} 신규 — 16 개 Role (BorderActive/Title/Path/ModeLexical/ModeVector/ModeHybrid/Selected/Hint/Heading/Warning/Error/Success/CitationMarker/Bullet/Body/BorderInactive) 을 dark + light 두 팔레트가 exhaustive match 로 매핑. 모든 Pane (library/search/ask/inspect/run/error_popup) 의 inline Style::default().fg(Color::*) 호출이 theme.style(Role::X) 로 격리됨. Config.ui.theme: String (default "dark") 신규. App.theme: ThemeApp::new 에서 Theme::from_name(&config.ui.theme) 로 build — 알 수 없는 값은 dark fallback (config 가 typo 로 죽지 않음). T 키 runtime toggle 은 mode machine (p9-fb-12) 미진행이라 skip — config 만으로 결정. p9-fb-11 (ask markdown render) 의 Theme 의존성 unblock. spec: tasks/p9/p9-fb-14-tui-color-theme.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-11) — TUI Ask 답변 본문 markdown 렌더. kebab-tui::markdown::render(text, &Theme) -> Vec<Line<'static>> 신규 — pulldown-cmark = "0.13" 위에서 inline (bold/italic/strikethrough/inline code/link)·block (heading H1-H6, ordered/unordered list with nesting, fenced code block, table, blockquote , horizontal rule) 변환. heading H1/H2 = Role::Heading, H3+ = Role::Title, link = Role::CitationMarker + UNDERLINE, code = Role::Hint. ask push_turn_lines 가 grounded 답변에서만 markdown 렌더; refusal (Role::Warning) / streaming (Role::Hint) 은 raw 로 두어 role color 시그널 보존. CLI kebab ask 출력은 raw markdown 그대로 (terminal 호환성). 매 frame 재 parse — pulldown 토크나이저가 µs/KB 라 비용 무시. spec: tasks/p9/p9-fb-11-ask-markdown-render.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-08) — TUI search async worker + generation counter. 기존 200ms debounce 후 kebab_app::search_with_config 동기 호출이 vector/hybrid 모드 50-200ms 동안 UI freeze 시키던 문제 해소. SearchStategeneration: u64 + worker_thread: Option<JoinHandle> + worker_rx: Option<Receiver<SearchWorkerMessage>> 신규. fire_search 가 spawn 만 하고 즉시 return — worker 가 별 thread 에서 검색 후 (generation, Result) 를 channel 로 post. run loop 가 매 tick poll_worker 로 try_recv, generation 일치 시 hits 적용 / 불일치 시 silently 폐기 (사용자가 더 빠르게 타이핑하면 stale 결과 자동 drop). debounce_due 가 searching && last_query == 현 input 케이스 추가 skip — in-flight worker 의 결과 기다리는 동안 동일 query 재 spawn 안 함. spec: tasks/p9/p9-fb-08-search-debounce.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-05)workspace.root path policy 명확화. kebab_config::expand_path_with_base(raw, data_dir, base_dir) -> PathBuf 신규 — 기존 expand_path (tilde + env 만) 위에 relative path resolution 추가, 절대/~/${VAR} 입력은 base_dir 무시. Config.source_dir: Option<PathBuf> 필드 (#[serde(skip)]) 신규 — from_file / loadpath.parent() 로 stamp. Config::resolve_workspace_root() helper 가 expand_path_with_base(&workspace.root, "", source_dir.unwrap_or(cwd)) 호출. kebab-app + kebab-source-fs 의 모든 workspace.root 사용 사이트가 cfg.resolve_workspace_root() 로 통일 — kebab-source-fs 의 fork 된 expand_tilde 헬퍼는 제거 (kebab-app 의 storage.data_dir 한 곳만 남음, P+ 통일 caveat). kebab init 가 생성하는 config.toml 위에 path policy 안내 헤더 코멘트 자동 prepend (절대/tilde/env/상대 + 상대 base = config dir). spec: tasks/p9/p9-fb-05-config-path-policy.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-19) — In-process LRU search cache + corpus_revision 카운터. SQLite V004 migration 으로 kv (key TEXT PK, value TEXT) 테이블 + corpus_revision = '0' seed. SqliteStore::corpus_revision() / bump_corpus_revision() 메서드 (UPDATE ... CAST AS INTEGER + 1 으로 atomic). kebab-app::ingest_with_config_cancellablenew + updated > 0 시 bump — no-op reingest 는 cache 보존. App.search_cache: Option<Mutex<LruCache<SearchCacheKey, Vec<SearchHit>>>> (capacity from config.search.cache_capacity, default 256, 0 = 비활성). SearchCacheKey = query_norm (NFKC + trim + lowercase) + mode + k + snippet_chars + embedding_version + chunker_version + corpus_revision snapshot. App::search 가 lookup → miss 시 search_uncached → put. search_uncached_with_config facade 추가, CLI kebab search --no-cache 로 bypass (디버깅용). frozen design §9 versioning 표에 corpus_revision row 추가. spec: tasks/p9/p9-fb-19-search-cache.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-17) — Multi-turn chat session 영속화 (storage 만 — UI 는 p9-fb-18). SQLite V005 migration (spec 의 V004 가 p9-fb-19 의 kv 와 충돌해서 V005 로 시프트, HOTFIXES) 으로 chat_sessions (session_id PK + created_at + updated_at + title + config_snapshot_json) + chat_turns (turn_id PK + session_id FK ON DELETE CASCADE + turn_index + question + answer + citations_json + created_at, UNIQUE(session_id, turn_index)) + idx_chat_turns_session 추가. kebab_core::ChatSessionRepo trait 6 메서드 (create_session / get_session / list_sessions / delete_session / append_turn / list_turns) + kebab_core::{ChatSessionRow, ChatTurnRow} 신규 export. kebab-store-sqlite::SqliteStore impl (별 chat_sessions.rs 모듈) — append_turn 이 insert + parent updated_at bump 을 같은 conn 에서 처리. frozen design §5 storage 에 §5.7a chat_sessions/turns 절 신설. spec: tasks/p9/p9-fb-17-chat-session-storage.md. unblocks p9-fb-18 (CLI session/repl).

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-18) — CLI kebab ask --session <id> (multi-turn). p9-fb-17 의 ChatSessionRepo 위에 kebab-app::App::ask_with_session(session_id, query, opts) -> Answer 메서드. 첫 호출 시 자동으로 chat_sessions row 생성 (title = 첫 question NFC trim 40 chars), 이후 호출은 list_turns 로 prior history 받아 RagPipeline::ask_with_history 호출 + 새 turn append. App 의 helper: first_question_title(question) (NFC + trim + 40 char cap, fallback "untitled") + blake3_truncate(input) (32-hex turn_id 생성). facade kebab_app::ask_with_session_with_config + CLI --session <id> flag 추가. --repl 은 spec 명시 사항이지만 stdin loop fixture 부담 으로 후속 task 로 deferral (out of scope per HANDOFF). spec: tasks/p9/p9-fb-18-cli-ask-session-repl.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-12 partial) — TUI vim-style mode machine (절반 ship — heuristic 제거는 follow-up). kebab_tui::Mode::{Normal, Insert} enum + Mode::auto_for(pane) (Library/Inspect/Jobs → Normal, Search/Ask → Insert) + Mode::label() ("-- NORMAL --" / "-- INSERT --") + App.mode: Mode field. run loop mode_intercept(app, key) 가 dispatch 전 intercept — Insert 에서 Esc → Normal (어디서나), Normal 에서 i → Insert (Library/Inspect/Jobs 만, Search/Ask 는 자동 Insert 라 i 가 typed char). 헤더 우측에 mode label colored (Insert = Role::Success green, Normal = Role::Heading cyan+bold). pane 전환 시 app.mode = Mode::auto_for(p) 자동 flip. Deferred (HOTFIXES entry): is_typing_mod (search) + input-empty heuristic (ask) 는 후속 PR 에서 mode-authoritative 로 교체 — 현재는 user-visible signal (label + auto flip + i/Esc) 만 ship, 키 dispatch 는 heuristic 유지. spec status in_progress (not completed). spec: tasks/p9/p9-fb-12-tui-mode-machine.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-12 follow-up) — heuristic 제거 (partial PR 의 deferred 부분 finalize). search::is_typing_mod (CTRL/ALT chord filter) 함수 삭제 + ask::handle_key_ask 의 input-empty heuristic 삭제. 새 dispatch: search::handle_key_searchi (chunk inspect) / g (editor jump) pre-pass 가 state.mode == Mode::Normal 일 때만 fire (Insert 에서는 typed char). main match 의 j/k/Char(c) 가 state.mode 로 분기 (Normal → 선택 이동, Insert → input.push). ask::handle_key_aske/j/k 도 동일 패턴 — Normal 에서 toggle/scroll, Insert 에서 input typing. 테스트 fixture (tests/search.rs::fresh_app, tests/ask.rs::fresh_app) 가 app.mode = Mode::auto_for(focus) 로 run-loop 동작 mirror. 기존 nav 테스트 (j_k_move, g_key_enqueues, e_toggles) 는 explicit app.mode = Mode::Normal 추가, 신규 4 테스트 (j_in_insert_types / arbitrary_char_in_normal_noop / e_types_in_insert / jk_scroll-in-normal-type-in-insert) 가 mode-authoritative 동작 pin. spec status in_progresscompleted. spec: tasks/p9/p9-fb-12-tui-mode-machine.md.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-10 partial) — TUI CJK rendering helpers. kebab-tui::input::{display_width, truncate_to_display_width} 신규 — unicode-width 위에서 column-단위 width 계산 (ASCII=1, Hangul/CJK/fullwidth=2, combining=0) + char-boundary 안전 truncate (wide char 를 split 없이 keep-or-omit, ellipsis 1 col). library.rs 의 중복 truncate_to_display_width private fn 제거 — 단일 source. 9 unit tests (ASCII / Hangul / Japanese / mixed / truncate fits·overflow·zero-cols·wide-char-boundary / String::pop char-aware sanity) + 1 integration render test (Korean + Japanese fixture, TestBackend 80×20, 한글/일본어 글자가 frame 에 살아남음 확인). spec 의 InputBuffer struct (cursor 가 column 단위 wide-char width 추적) 도입은 follow-up — Ask/Search/Editor pane 의 String + cursor 일괄 마이그레이션이 회귀 표면이 커서 helper 만 먼저 머지. backspace 는 모든 pane 이 이미 String::pop() 사용 (char-aware) → byte-boundary 안전성 helper 없이도 확보. crossterm 0.28 이 native IME composing 미노출 — preedit handling out of scope. spec status plannedin_progress. spec: tasks/p9/p9-fb-10-tui-cjk-input.md.

  • 2026-05-04 P9 post-도그푸딩 (p9-fb-23) — Incremental ingest. 사용자 도그푸딩 피드백: 변하지 않은 문서는 다시 ingest 하지 않기. blake3 checksum + parser_version + chunker_version + embedding_version 4개 input 이 모두 일치할 때 parse/chunk/embed/vector upsert 모두 회피. SQLite V006 마이그레이션 — documentslast_chunker_version + last_embedding_version 컬럼 추가. 신규 IngestItemKind::Unchanged variant + IngestReport.unchanged + AggregateCounts.unchanged (wire schema additive). IngestOpts { progress, cancel, force_reingest } struct 도입 — AskOpts 패턴. --force-reingest CLI flag 로 skip 우회. 비용 dominator (fastembed) 가 변경된 / 새 doc 에만 발생. spec: tasks/p9/p9-fb-23-incremental-ingest.md. HOTFIXES 2026-05-04 — p9-fb-23 항목이 version cascade 명시 동작의 source of truth.

  • 2026-05-05 P9 post-도그푸딩 (p9-fb-25) — Config 의 workspace.include 필드 제거 + 지원 형식 가시성. 사용자 도그푸딩 피드백: include + exclude 동시 존재가 case 4 (둘 다 매치 안 함) 의미 모호 + 어차피 처리 가능 형식 (md / png / jpg / pdf) 이 정해져 있으니 명시 필요. WorkspaceCfg.include 제거 (옛 config 의 include = [...] 은 silently 무시 + 단발 deprecation warning). IngestItem.warnings 가 Skipped 시 사유 ("unsupported media type: .docx" 등) 채움. IngestReport.skipped_by_extension: BTreeMap<String, u32> 신규 (additive wire — release 트리거 안 됨). CLI / TUI summary 에 breakdown 표시 ("5 skipped: 3 docx, 1 txt, 1 epub"). README + kebab init 헤더 주석에 지원 형식 명시. spec: tasks/p9/p9-fb-25-config-include-removal.md. HOTFIXES 2026-05-05 — p9-fb-25 가 source of truth.

  • 2026-05-04 P9 post-도그푸딩 (p9-fb-24) — TUI status/key bar + Library 컬럼 헤더 + Ask/Inspect PgUp/PgDn. 사용자 도그푸딩 3 건 (Library 컬럼 의미 부재, 페이지 스크롤 키 부재, 상태바 + 버전 정보 항상 노출 요청) 을 단일 PR 로 통합. bottom 영역을 status bar (1 row, version + pane + docs + dynamic state) + key hint bar (1 row, 기존 footer_hints 그대로) 두 줄로 분할; 기존 ingest progress dedicated row 는 status bar 의 dynamic slot 에 흡수 (priority cascade: streaming → searching → indexing → idle). Library List 위에 format_doc_header 행 + Layout 분할로 헤더 표시 (TITLE / TAGS / UPDATED / CHUNKS, display-width 정렬). kebab-tui::pager::PAGE_STEP = 10 신규 — Ask 의 PgUp/PgDn 추가 + Inspect 의 기존 +/-10 hardcode 가 같은 상수 참조로 통일. Ask 의 page-scroll 은 j/k 와 동일하게 follow_tail = false 로 freeze. spec: tasks/p9/p9-fb-24-tui-affordances.md. HOTFIXES 2026-05-04 — p9-fb-24 항목이 footer 단행 row (p9-fb-13) + ingest dedicated row (p9-fb-03) 와의 layout 충돌의 source of truth.

  • 2026-05-04 P9 post-도그푸딩 (p9-fb-22) — TUI 입력 cursor mid-string 편집 + Ask follow-tail auto-scroll. Gitea #94 (입력 후 커서 이동 안 됨) + #95 (새 응답 자동 스크롤 안 됨) 두 건. InputBuffer 의 cursor 모델을 byte-position 기반으로 재구성 — cursor 가 끝일 때 기존 append 동작과 backwards-compatible, mid-string 일 때는 ←/→/Home/End/Delete 로 편집. AskStatefollow_tail: bool (default true). Paragraph::line_count(width) (ratatui unstable-rendered-line-info feature 활성화) 로 매 프레임 wrapped row 수 계산해 follow-tail 시 scroll 을 bottom 에 pin. j/k 가 follow-tail 끄고 Shift-G 가 다시 켬. 12 신규 InputBuffer unit + 6 신규 Ask integration. spec: tasks/p9/p9-fb-22-tui-cursor-and-autoscroll.md. HOTFIXES 항목 2026-05-04 가 live cursor 모델 source of truth.

  • 2026-05-03 P9 post-도그푸딩 (p9-fb-21)i 가 universal Normal→Insert toggle (모든 pane). 이전 mode_intercept 는 Library/Inspect/Jobs 만 i intercept 였고 Search/Ask 는 fall-through (자동 INSERT 가정). 사용자가 Esc 로 NORMAL 로 빠진 후 Insert 복귀 키 없어 dead-end → 도그푸딩에서 보고됨. mode_intercept 의 (Char('i'), Normal, _) arm 이 pane 무관 모두 INSERT flip. Search 의 chunk inspect 키 io rebind (vim "open") 으로 충돌 해소. footer hint 모든 (pane, mode, filter) 조합 첫 fragment = F1 도움말 (cheatsheet binding discoverability). Search/Ask Normal hint 에 i 입력모드 fragment 추가. cheatsheet popup Global/Search/Ask section 갱신. 6 신규 unit + 3 기존 갱신. spec: tasks/p9/p9-fb-21-tui-insert-key-discoverability.md (status completed 직접). HOTFIXES 항목이 Search io rebind 의 source of truth.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-10 follow-up) — InputBuffer struct + 모든 text-input pane 마이그레이션 + cursor column 정렬. kebab-tui::input::InputBuffer { content, cursor_col } 신규 — push_char / pop_char / clear / take 가 wide-char 단위로 cursor_col 진행 (ASCII=1, Hangul/CJK=2, combining=0). SearchState.input / AskState.input / FilterEdit.{tags_buf, lang_buf} 가 InputBuffer 로 교체. render 단계에서 f.set_cursor_position(...)block.inner(area) 기반 prompt 폭 + cursor_col 으로 caret 을 정확한 column 에 배치 (right-edge clamp). ratatui 0.28 의 cursor visibility 는 cursor_position Some/None 으로 자동 결정 — Search/Ask/Filter 가 Some 이라 caret 보임, Library/Inspect 는 None 이라 hidden. Korean lexical 검색은 crates/kebab-app/tests/search_korean.rs 에서 ingest → search → 결과 한 건 이상 + Korean 파일 stem 매칭 assert 로 회귀 핀. lexical_query test helper 가 crates/kebab-app/tests/common/mod.rs 로 promotion. spec status in_progresscompleted. spec: tasks/p9/p9-fb-10-tui-cjk-input.md.

  • 2026-05-07 P9 post-도그푸딩 (p9-fb-27)kebab schema [--json] introspection 명령 + error.v1 wire 도입. 정적 (wire schemas / capabilities / models) + 동적 (stats) 한 번에. --json 모드에서 fatal error 가 stderr ndjson 으로 emit (비 --json 은 기존 stderr text 유지). exit code 0/1/2/3 unchanged — error.v1.code 가 fine-grained 분기. fb-30 MCP initialize capability matrix 의 prerequisite. spec: tasks/p9/p9-fb-27-introspection-and-error-wire.md. design: docs/superpowers/specs/2026-05-07-p9-fb-27-introspection-and-error-wire-design.md.

  • 2026-05-03 P9 도그푸딩 피드백 20/20 tasks/p9/p9-fb-01..20 모든 spec status completed. 사용자가 kebab 직접 돌려서 수집한 UX 잡음 (ingest 진행 표시 부재, mode 혼란, CJK column drift, multi-turn 부재, citation 부재 등) 이 모두 코드 또는 spec-acknowledged-deferred 형태로 해소. 도그푸딩 사이클 한 바퀴 완성 — P9-5 desktop tauri 와 별개로 TUI/CLI 사용자 경험 측면은 한 단계 안정화. P9 phase row 는 P9-5 미진행이라 🟡 유지.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-13 follow-up) — verb-form hint line 재구성. pub fn footer_hints(focus: Pane, mode: Mode, filter_open: bool) -> &'static str 신규 (run.rs). 한국어 동사구 ("위로" / "아래로" / "필터" / "타이핑 검색어" / "Esc 로 NORMAL 모드" 등) + mode-aware (NORMAL = navigation verbs, INSERT = typing + Esc reminder) + Library filter overlay 별 분기. 8 unit tests pin 모든 (pane, mode, filter) 조합 — exhaustive non-empty + Library Normal/filter, Search Normal/Insert, Ask Normal/Insert, Inspect Normal 별 verb fragment 존재 검증. spec status in_progresscompleted — p9-fb-13 partial 의 deferred verb-form 항목이 닫힘.

  • 2026-05-03 P9 도그푸딩 후속 (p9-fb-13) — TUI cheatsheet popup. kebab-tui::cheatsheet::render_cheatsheet(f, area, app) 신규 — 70%/60% centered modal, sections (Global / Library / Search / Ask / Inspect) + global toggle table + 현재 focused pane footer. App.cheatsheet_visible: bool 필드 + pub fn cheatsheet_visible() getter. run loop cheatsheet_intercept(app, key) 가 mode_intercept 보다 먼저 dispatch — F1 토글 (open/close), Esc 가 visible 일 때 닫기 (mode_intercept 를 우회해서 cheatsheet 닫기 가 mode flip 도 발동시키지 않도록), 그 외 키는 fall-through (popup 열린 채 navigation 가능). modifier-bearing F1 (Ctrl-F1 등) 은 무시. HOTFIXES 기록: spec 의 ? trigger 가 Library 의 quick-Ask binding 과 충돌해서 F1 으로 rebind. spec 의 verb-form hint line 재구성은 별 후속 PR (기존 footer 가 동일 역할). spec status plannedin_progress (verb hint deferral 으로 partial). spec: tasks/p9/p9-fb-13-tui-cheatsheet.md.

다음 task 후보

구조적으로 미완인 component 는 P9-5 하나뿐. 나머지는 도그푸딩 follow-up (아래 "P10 dogfooding 백로그") 또는 사용자 결정 대기.

  • P9-5 desktop tauri — 마지막 남은 P9 component. kebab-desktop crate + Tauri 앱, 별도 분기. PDF citation rendering UI 가치 큼. 사용자 우선순위 (P9 우선 · 책/PDF 위주) 와 부합.
  • P10 도그푸딩 round 2 follow-up v0.17.0 cut (2026-05-24) 으로 세 항목 모두 closure (한국어 trigram PR-A + C typedef alias PR-B + code_lang_chunk_breakdown additive PR-C). 상세 cross-link: 아래 "P10 dogfooding 백로그" 절 + tasks/HOTFIXES.md (2026-05-24 PR-A/B/C).
  • P8 audio brainstorm — whisper-rs 시스템 dep 받을지 / 외부 transcription endpoint 사용할지 사용자 결정 필요. 사용자 패턴 (책+PDF 위주, audio 의향 없음) 상 보류.
  • fb-41 multi-hop reasoning 미구현, XL, eval 인프라 선행 + brainstorm 필요.
  • Rust symbol path retrofit — Rust code-rust-ast-v1 symbol 이 file-scope-only (1B+ 는 module prefix). code-rust-ast-v2 bump + Rust corpus re-ingest 비용 → 사용자 명시 요청까지 보류. HOTFIXES 2026-05-20.

v0.20.0 sub-item 1 (PDF scanned OCR) 머지 후 priorities (2026-05-28, 사용자 결정)

PR #189 (2026-05-28 머지, commit 09333d0) 으로 PDF scanned OCR (qwen2.5vl:3b vision LLM) + 4 round bugfix (#2/#3/#4/#6/#7/#9/#10/#11/#13/#14) + ingest log feature 가 main 으로 진입. 다음 작업 순서 = C → B → A → G.

  • C — 한국어 morphological tokenizer (Bug #8 follow-up) 다음 우선.

    • V007 trigram 의 ≥3 char query 제약 (HOTFIXES 2026-05-22) — '한국' 같은 2-char 한국어 query 0 hit. 본격 사용자 search experience 의 가장 큰 surface.
    • 가능한 path: jieba-rs / koma / komoran 같은 morphological tokenizer 도입 → FTS5 의 external content + custom tokenize. 또는 tokenize='unicode61' + 별 token table 의 dual-index.
    • scope: search index 재빌드 cascade (corpus_revision bump) + 기존 V007 trigram 보존 (backward-compat) 여부 결정. 별 sub-item.
    • 별 sub-item: spec/plan/executor cycle.
  • B — OCR dense page coverage C 다음.

    • metro-korea.pdf page 8/13 timeout (180s, dense newspaper article). vision LLM 의 output token 과대 → 정상 timeout.
    • 가능한 path: (a) per-page max_pixels 동적 조정 (high-resolution page 만 축소), (b) column-level sub-region OCR (newspaper layout 분할 후 OCR call 분리), (c) model upgrade (qwen2.5vl:7b — Ollama 모델 변경 + max_pixels trade-off), (d) OCR timeout 점진 축소 (180s → 120s → 90s) — round 마다 p90 측정 후.
    • mojibake.pdf pdf_ocr_pages: 0 (round 1 부터 동일) — text-detect path fallback 강화 검토.
    • 별 sub-item.
  • A — v0.20 의 deferred sub-items (frozen design contract) B 다음.

    • sub-item 2 — Multi-region image dispatch (OcrText.regions bbox 분리) — image OCR + PDF column-aware OCR.
    • sub-item 3 — PDF normalize integration (ParsedPdfPage production caller + build_canonical_document_from_pdf_pages + cross-page reference graph).
    • TODO #4 — Per-page image / table extraction (PDF figure / table extract).
    • TODO #5 — Enricher trait 도입 — OCR + caption 의 Extractor trait 통합 (post-extract enrichment 의 generalization).
    • 각 sub-item 별 spec/plan/executor cycle.
  • G — v0.20.1 patch release + release notes A 머지 후 (또는 C/B 시점에 따라 조기 cut).

    • CLAUDE.md release 룰 — sub-item 1 base + bugfix1-4 + log feature + logging r2 누적 → minor surface 변경 다수 + wire schema additive minor + config 신규 → v0.20.1 patch bump + release notes.
    • 핵심 surface (사용자 도그푸딩 가이드 형식):
      • OCR timeout default 180s (HOTFIXES 2026-05-28).
      • [logging] config section (default enabled) + {state_dir}/logs/ingest-{run_id}.ndjson 자동 생성.
      • [logging] keep_recent_runs (100) + retention_days (30) — OR-on-stale cleanup.
      • ingest_progress.v1.pdf_ocr_finished 의 4 추가 field (image_byte_size, image_width, image_height, failure_reason) — image_w/h 가 round 2 (PR #190) 에서 실제 capture.
      • schema.v1.modelsactive_parsers + active_chunkers (additive minor).
      • V008 migration — pdf_ocr_events table (per-OCR-call historical record).
      • 새 wire schemas — ocr_stats.v1 + ocr_failures.v1 (CLI inspect 의 emit).
      • CLI kebab inspect ocr-stats + kebab inspect ocr-failures — sweet-spot 점진 분석.
      • CLI --media code first-class, empty query → invalid_input, --config missing → config_not_found + exit 2.
      • capabilities.streaming_ask + single_file_ingest 가 true (이전 false 거짓 정정).
    • bump 작업: workspace Cargo.toml version → 0.20.1, tag, gitea-release.

v0.20 후속 bug catalog (non-blocking known)

본 PR #189 dogfood 에서 falsified 또는 design constraint 로 분류 — fix 안 함:

  • Bug #8 (V007 trigram 2-char query 한계) → 위 C 항목.
  • Bug #12 (Code block wire .code field, .text 가 아닌 jq fallback artifact) — falsified.
  • ask 한국어 query phrasing-sensitive refusal — RAG corner case / NLI gate behavior. 별도 brainstorm.

Logging feature enhancements — closed (PR #190, 2026-05-28 merged commit 7bbdc89a)

logging round 2 (PR #190) 으로 4 enhancement 모두 closed:

  • image_width + image_height capture (raster JPEG decode).
  • SQLite mirror (V008 pdf_ocr_events table + dual-write).
  • CLI query (kebab inspect ocr-stats + ocr-failuresocr_stats.v1 + ocr_failures.v1 wire schemas).
  • log retention (keep_recent_runs + retention_days — file + SQLite cleanup).

P9 dogfooding 백로그 (fb-26 ~ fb-42) — release 분할

2026-05-06 도그푸딩 누적 피드백 + "AI agent 가 kebab 을 쓰게 한다" 궁극 목표용 surface 확장. cascade 영향 / 분량 고려해 한 minor 에 묶지 않고 분할.

  • 0.3.0 — agent foundation cut 2026-05-07: fb-26 (log), fb-27 (introspection/error wire), fb-28 (readonly/quiet). fb-29 (daemon)🚫 deferred — fb-30 stdio MCP 가 동일 가치를 daemon 복잡도 없이 제공.
  • 0.4.0 — agent integration (MCP) cut: fb-30 (MCP stdio), fb-31 (single-file/stdin ingest).
  • 0.5.0 — agent surface refinement (additive) cut 2026-05-10: fb-32 (stale doc indicator), fb-33 (streaming ask), fb-34 (output budget controls), fb-35 (verbatim fetch), fb-36 (search filter args), fb-37 (trace + stats). 모두 wire schema additive minor.
  • 0.6.0 — RAG quality 대부분 머지 (2026-05-10): fb-38 (score semantics) , fb-39 (eval foundation — precision_at_k_chunk metric) , fb-39b (embedding upgrade — multilingual-e5-large default) , fb-40 (fact-grounded answer / rag-v2 prompt) . 잔여 = fb-39 의 retrieval precision lever 실제 적용 (eval golden set 확장 선행 필요).
  • 0.7.0 또는 P+: fb-41 (multi-hop reasoning, XL) — 미구현 · brainstorm 필요; fb-42 (bulk multi-query) 머지 (2026-05-10, bulk only — rerank hint 은 deferred).

각 fb spec frontmatter 의 target_version 필드가 source of truth. INDEX.md 의 release subheader 도 동일 grouping.

P10 dogfooding 백로그 (2026-05-22 round 2)

P10 종합 도그푸딩 round 2 (/build/cache/dogfood-p10b/, OSS 8 repo + 한국어 위키 문서 10편) 에서 발견된 follow-up 후보. 자세한 내용 + 우선순위 근거는 tasks/HOTFIXES.md (2026-05-22).

  • 한국어 lexical tokenizer v0.17.0 (2026-05-24) PR-A 머지 (#159). V007 trigram migration 자동 backfill + build_match_string 재설계 + CLI/TUI/wire hint. HOTFIXES 2026-05-24 PR-A 참조.
  • code_lang_chunk_breakdown chunk 단위 집계 (LOW) v0.17.0 (2026-05-24) PR-C 머지 (#161). schema.v1.stats additive 필드. HOTFIXES 2026-05-24 PR-C 참조.
  • C typedef-wrapped struct (LOW) v0.17.0 (2026-05-24) PR-B 머지 (#160). type_definition 분기 + PARSER_VERSION code-c-v2 bump + orphan purge cascade. HOTFIXES 2026-05-24 PR-B 참조.
  • ranking glue chunk 편향 (deferred) — 자동 heuristic 은 user intent misalignment 위험. 사용자 명시 요청 전까지 surface 변경 0 유지. 1주+ 실사용 후 재 brainstorm.

검증된 운영 동작 (release binary, fastembed enabled)

P7-3 머지 직후 25 시나리오 smoke 통과 — markdown + image + PDF 5 자산 워크스페이스에서 doctor / ingest / list / inspect / search (lex/vec/hybrid) / re-ingest / byte-edit re-ingest / corrupt PDF / RAG ask + page citation 모두. 자세한 시나리오 표는 conversation 기록 참조; 워크스페이스에 직접 돌려보는 절차는 docs/SMOKE.md.