Commit Graph

61 Commits

Author SHA1 Message Date
th-kim0823
c62a8ff503 docs(fb-39b): design + HOTFIXES + new task spec + INDEX + README + SMOKE
Tasks 4 + 5: comprehensive doc update for embedding upgrade (multilingual-e5-large).

- design §5 + §9: update embedding_model / dimensions references (384 -> 1024)
- HOTFIXES: add fb-39b entry with user re-ingest procedure + backwards-compat notes
- tasks/p9-fb-39b-embedding-upgrade.md: new task spec (completed status)
- INDEX.md: add fb-39b row under RAG quality phase
- fb-39 task banner: append fb-39b link as lever implementation
- README: update config defaults + fastembed model size + embedding field docs
- SMOKE.md: append embedding upgrade verification section with e5-small -> e5-large sequence

Wire schema: no change (additive at config level, new table created by existing code).
Binary version: 0.6.0 -> 0.7.0 (cascade rule: embedding_model change = minor bump).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 23:28:48 +09:00
th-kim0823
d5321701ea plan(fb-39b): embedding upgrade implementation plan
5 tasks: kebab-embed-local resolve_model arm + check_dim test,
kebab-config defaults + TOML template flip, cross-crate fixture
sweep (likely no-op since most tests use provider=none), docs
(design + HOTFIXES + new task spec + INDEX), README + SMOKE
walkthrough.

Post-merge: 0.6 → 0.7 binary bump per CLAUDE.md cascade rule.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 23:02:37 +09:00
th-kim0823
2c3461c465 spec(fb-39b): embedding model upgrade design
- multilingual-e5-small (384 dim) → multilingual-e5-large (1024 dim)
- Cascade: embedding_version bump → fb-23 incremental ingest
  re-embeds all chunks
- Migration policy: dim mismatch detection at LanceVectorStore::open
  → error.v1 (code = embedding_dim_mismatch) + hint
  "kebab reset --vector-only && kebab ingest"
- Config defaults flip (model + dimensions). User TOML pinning small
  preserves backwards-compat
- bge-m3 deferred (fastembed enum 미포함, UserDefinedEmbeddingModel
  ONNX path 별도)
- Release trigger: 0.6 → 0.7 minor bump per CLAUDE.md cascade rule

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:59:03 +09:00
th-kim0823
f00fb376fe docs(fb-39): golden header + design §10.3 eval + spec status + INDEX
Strengthen fixtures/golden_queries.yaml header with precision_at_k_chunk
explanation + measurement guidance. Add §10.3 Eval metrics section to
frozen design documenting retrieval metrics (hit@k, MRR, recall@k_doc,
P@k_chunk) + groundedness metrics. Flip p9-fb-39 spec status from open
→ completed (eval foundation only, lever deferral noted). Update
tasks/INDEX.md fb-39 row mirror to fb-42 (merged, deferred note).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:35:15 +09:00
th-kim0823
f303c76f52 plan(fb-39): eval foundation implementation plan
4 tasks: AggregateMetrics.precision_at_k_chunk field + serde
backwards-compat, compute aggregation in loop with 5 unit tests,
golden YAML header doc strengthening, design §11 + INDEX + status
flip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:19:44 +09:00
th-kim0823
cd5b1e3bfc spec(fb-39): eval foundation design (P@k metric)
- AggregateMetrics 에 precision_at_k_chunk: BTreeMap<u32, f32>
  (P@5, P@10) 추가, binary relevance via expected_chunk_ids
- Denominator = k 고정 (hits.len() < k 도 precision 손실 간주)
- Empty expected_chunk_ids query 는 skip (hit_at_k 동일 정책)
- Lever 적용 (chunk policy / RRF / cross-encoder / embedding) 은
  본 spec 범위 외 — fb-39b 이후 별도 task
- Golden set schema 무변경, shipped fixtures 헤더 주석만 강화

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:05:09 +09:00
th-kim0823
441f1192ee docs(fb-42): wire schema + README + SMOKE + design + SKILL + INDEX
- Add bulk_search_item.v1 + bulk_search_response.v1 wire schemas
- Register both in WIRE_SCHEMAS const
- README: --bulk flag mention + MCP tool list 7→8 (bulk_search)
- SMOKE: bulk multi-query walkthrough (CLI + MCP equivalent)
- Design §2.2: Bulk multi-query (fb-42) subsection (additive minor)
- SKILL: mcp__kebab__bulk_search section + tool table row
- Task spec status open→completed, banner replaced
- INDEX: fb-42 row 머지 (rerank hint deferred)
- Fix: missed Capabilities {bulk_search} in cli wire.rs test (Task 7 leftover)
- Fix: missed tools.len() 7→8 in cli_mcp_smoke (Task 5 leftover)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 21:07:36 +09:00
th-kim0823
de9016fe16 plan(fb-42): bulk multi-query implementation plan
8 tasks: kebab-core types, kebab-app bulk_search_with_config facade
(cap 100 + per-query error policy), CLI --bulk flag + stdin ndjson +
output stream, CLI integration tests, MCP bulk_search tool +
registration + tools_list count bump, MCP integration tests,
capability flag, wire schemas + README + SMOKE + design + SKILL +
status flip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 20:10:39 +09:00
th-kim0823
35df15df99 spec(fb-42): bulk multi-query design (rerank hint deferred)
- CLI: kebab search --bulk + stdin ndjson → stdout per-query ndjson
- MCP: 신규 kebab__bulk_search tool + JSON envelope (results + summary)
- Sequential for-loop, App instance 재사용 (cache amortize)
- Per-query error policy: continue + per-item error.v1
- Limits: queries.len() <= 100
- Capability flag bulk_search 신규
- Rerank hint 별도 task (fb-39 cross-encoder 설계 후)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 20:05:27 +09:00
th-kim0823
600c6182fc docs(fb-40): rag-v2 prompt + README + design + SKILL + INDEX
- README: [rag] prompt_template_version default rag-v2 + V2 강화 3 규칙
- design §7: rag-v2 본문 + V1 legacy note
- SKILL.md: mcp__kebab__ask 응답 행태 변화 안내
- task spec: status open → completed, design + plan 링크
- INDEX: fb-40  머지 (2026-05-10)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 19:37:28 +09:00
th-kim0823
6d6eb442be plan(fb-40): fact-grounded answer implementation plan
6 tasks: SYSTEM_PROMPT_RAG_V2 + system_prompt_for helper, pipeline
dispatch wiring, config default flip rag-v1 → rag-v2, test fixture
cleanup, integration tests (rag-v1 / rag-v2 / unknown via
CapturingLm wrapper around MockLanguageModel), docs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 18:58:35 +09:00
th-kim0823
28d3250546 spec(fb-40): fact-grounded answer design
- rag-v1 → rag-v2 system prompt with 3 신규 규칙 (verbatim span 인용 자도 /
  학습 지식 동원 금지 / 추측 금지)
- system_prompt_for(version) helper dispatch in pipeline
- config default prompt_template_version "rag-v1" → "rag-v2", V1 legacy
  kept for backwards-compat
- Lever C (pre-LLM gate) already shipped (RefusalReason::ScoreGate),
  out of scope here

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 18:55:05 +09:00
th-kim0823
c864bd007f docs(fb-38): wire schema + README + design + SKILL + INDEX 2026-05-10 18:21:55 +09:00
th-kim0823
56f20b7235 plan(fb-38): score semantics implementation plan
7 tasks: kebab-core ScoreKind enum + SearchHit field, lexical Bm25
labeling, vector Cosine, hybrid Rrf + search_with_trace pass-through,
cross-crate SearchHit literal cleanup, CLI integration test, docs
(wire schema + README + design + SKILL + INDEX).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 17:45:57 +09:00
th-kim0823
0359bd9682 spec(fb-38): score semantics design
- search_hit.v1 에 optional score_kind 필드 (rrf | bm25 | cosine)
- LexicalRetriever → Bm25, VectorRetriever → Cosine, HybridRetriever → Rrf
- fb-37 search_with_trace 의 mode-dispatch hits 는 underlying retriever 의
  score_kind 그대로 보존
- README + design §4 + SKILL 에 RRF 수식 전체 + "ranking signal, NOT confidence"
  안내, agent 용 trust threshold 는 nested retrieval.{lexical,vector}_score
- additive minor wire — schema bump 없음

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 17:40:47 +09:00
th-kim0823
fb31befef1 plan(fb-37): trace + stats implementation plan
10 tasks: kebab-core types, store breakdowns/index_bytes helpers,
extended CountSummary + Stats wire mirror, HybridRetriever
search_with_trace, App SearchResponse.trace threading, CLI --trace
flag, integration tests, MCP SearchInput.trace, TUI TracePopup,
docs (wire schema + README + SMOKE + INDEX + SKILL).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 12:14:26 +09:00
th-kim0823
5f6b2fa259 spec(fb-37): trace + stats design
- search --trace boolean flag, additive optional `trace` field on search_response.v1
- HybridRetriever search_with_trace returns (hits, SearchTrace) — lex/vec/rrf_inputs + per-stage timing
- cache bypass when --trace (debug intent)
- schema.v1.stats extended with media_breakdown / lang_breakdown / index_bytes / stale_doc_count
- TUI search pane `t` keystroke opens TracePopup
- additive minor wire — no schema bump

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 12:05:31 +09:00
th-kim0823
31c1e05951 plan(fb-36): search filter args implementation plan
9 tasks: SearchFilters extension, lexical SQL WHERE, vector
filter_chunks mirror, CLI 7 flags, integration tests, MCP
SearchInput extension, workspace test/clippy, docs, smoke+PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 03:34:39 +09:00
th-kim0823
7210386699 spec(fb-36): search filter args — design
`kebab search` 에 7 flag 노출 (기존 4 + 신규 3):
- --tag (반복) / --lang / --path-glob / --trust-min (기존 SearchFilters)
- --media (csv) / --ingested-after (RFC3339) / --doc-id (신규)

filter layer = SQLite WHERE (lexical) + over-fetch+post-filter
(vector). AND 결합. wire schema 무변경 (input only).

`SearchFilters` 3 필드 additive (#[serde(default)] 로 backwards-
compat). MCP SearchInput 7 optional 필드 추가. invalid RFC3339 →
error.v1.code = config_invalid.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 03:26:40 +09:00
th-kim0823
7dddc1d706 fix(fb-35): address PR #126 round 1 review
- fetch_span: panic-fix on line_start > total / empty doc
  (return empty text + effective_end = line_start - 1 instead of
  out-of-bounds slice)
- truncated: reserved for budget-driven truncation only; line
  range clamp signaled via effective_end < line_end
- spec / SKILL.md / README: align rejection wording to "PDF /
  audio" (matches code; Image OCR allowed for span)
- store: warning comment on list_chunk_ids_for_doc — chunk_id
  hash sort does NOT preserve document position; real fix is a
  chunks.ordinal column, tracked as follow-up
- surrounding_chunks: saturating_add to defend against u32::MAX
  context arg on 32-bit targets
- tests: line_start > total returns empty + chunk context at
  doc boundary clamps lower bound

Deferred nits (follow-up): table-separator strict CommonMark form;
MCP per-mode strict validation; CLI chunk_id truncation in plain
output. None block correctness.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 00:45:29 +09:00
th-kim0823
353aa5cc78 plan(fb-35): verbatim fetch implementation plan
11 tasks: domain types, wire schema, App::fetch chunk/doc/span
modes (3 separate tasks for incremental TDD), CLI subcommand,
CLI integration tests, MCP tool, workspace+clippy gate, docs,
smoke+PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 23:31:29 +09:00
th-kim0823
4eda9c317d spec(fb-35): verbatim fetch — design
`kebab fetch chunk|doc|span` 신규 subcommand + MCP `kebab__fetch`
tool. wire = `fetch_result.v1` (kind discriminator).

source = CanonicalDocument / chunks.text 정규화된 markdown (raw
bytes 미노출). chunk mode `--context N` = ordinal ±N. doc/span
mode = fb-34 budget 재사용 (chars/4). PDF/audio span 은
`error.v1.code = span_not_supported` 거절.

신규 error codes: chunk_not_found / doc_not_found /
span_not_supported / invalid_input. fb-34 StructuredError
wrapper 재사용.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 23:21:01 +09:00
th-kim0823
dbb7b54d5d plan(fb-34): output budget controls implementation plan
11 tasks: SearchOpts (kebab-core), cursor module + base64 dep
(kebab-app), error_wire stale_cursor convention, App::search_with_opts
+ SearchResponse + budget loop, wire schema search_response.v1, CLI
flags + plain truncated hint, CLI integration tests, MCP wrapper +
inputs, workspace+clippy gate, docs (README/SMOKE/INDEX/HOTFIXES/
skill), smoke+PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 17:43:26 +09:00
th-kim0823
a80f65c6f2 spec(fb-34): output budget controls — design
`kebab search` 에 --max-tokens / --snippet-chars / --cursor 신규.
chars/4 token approximation. truncate priority: snippet → k → 멈춤
(최소 1 hit 보장). cursor = opaque base64(offset + corpus_revision)
— mismatch 시 error.v1.code = stale_cursor.

wire breaking: stdout array → search_response.v1 wrapper. agent 갱신
필요. App::search 시그니처는 thin wrapper 로 보존 (TUI 무영향).

ask path 는 scope out (rag.max_context_tokens 가 이미 budget 담당).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 17:36:51 +09:00
th-kim0823
0ca9b1d5c3 plan(fb-33): streaming ask implementation plan
10 tasks: StreamEvent enum + AskOpts switch (kebab-core), pipeline
emits + cancel branch (kebab-rag), kebab-app re-exports, TUI
worker adapt, wire schema answer_event.v1, CLI --stream flag +
ndjson stderr driver + BrokenPipe cancel, integration tests
(Ollama-gated), workspace+clippy gate, docs, smoke+PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:16:42 +09:00
th-kim0823
4949775c8b spec(fb-33): streaming ask (ndjson delta) — design
3-variant StreamEvent enum (RetrievalDone / Token / Final) 을 통해
RagPipeline 이 retrieval / per-token / final 단계를 sink 로 발사.
CLI `kebab ask --stream` 이 ndjson event 를 stderr 로 흘리고 final
stdout line 은 기존 answer.v1 그대로 (ingest_progress.v1 패턴).
Cancel = stdout 닫힘 → SendError → LLM stream break +
RefusalReason::LlmStreamAborted 로 partial answer 기록.
MCP streaming 은 v0.5+ 별도 검토 (scope out).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:10:08 +09:00
th-kim0823
4728a87957 plan(fb-32): stale doc indicator implementation plan
15 tasks covering domain (kebab-core SearchHit + AnswerCitation),
config (SearchCfg.stale_threshold_days), retrievers (lexical + vector
JOIN documents.updated_at), App facade (staleness module + cache
re-stamp), wire schema, CLI plain [stale] tag, TUI [STALE] Warning
badge, snapshot fan-out, docs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 00:40:46 +09:00
th-kim0823
401a47fb43 spec(fb-32): stale doc indicator — design
검색 hit / RAG citation 에 indexed_at + stale 두 wire 필드 추가.
documents.updated_at 재활용 (V006 incremental ingest 가 자연 source-of-truth).
config [search] stale_threshold_days = 30 default. additive minor wire.
TUI Warning role / CLI plain [stale] tag / agent --json 동시 surface.
자동 재 ingest 는 out of scope.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:00:10 +09:00
th-kim0823
2de28c43da docs(plan): fb-26 + fb-28 + schema-sync implementation plan
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 19:18:27 +09:00
th-kim0823
9d96504bd9 docs(spec): fb-26 + fb-28 + schema-sync design doc
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 19:11:47 +09:00
th-kim0823
345a4f363a 📝 docs: sync README / HANDOFF / CLAUDE / skill / design for fb-31
- README 명령 표 에 `kebab ingest-file` + `kebab ingest-stdin` 두 row + MCP tool list 4 → 6.
- HANDOFF post-도그푸딩 항목 한 줄.
- CLAUDE.md `_external/` 디렉토리 + naming convention 한 줄.
- integrations skill — Recipe D (agent fetched web doc) + MCP tool list 갱신.
- design §6.7 `_external/` subdirectory 절 신설.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 18:16:45 +09:00
th-kim0823
b7c85e8887 📝 docs(plan): p9-fb-31 single-file / stdin ingest implementation plan
12-task plan covering:
- kebab-app::external module (4 helpers + 12 unit tests) — Task 1
- kebab-app::ingest_file_with_config facade — Task 2
- kebab-app integration test — Task 3
- kebab-app::ingest_stdin_with_config facade — Task 4
- kebab-app integration test — Task 5
- kebab-cli Cmd::IngestFile + Cmd::IngestStdin arms — Tasks 6 + 7
- kebab-cli spawn-based integration tests — Task 8
- kebab-mcp ingest_file + ingest_stdin tools (4 → 6) — Task 9
- kebab-mcp integration tests — Task 10
- doc sync (README + HANDOFF + CLAUDE + skill + design §6.3) — Task 11
- HOTFIXES + status flip + final verification — Task 12

Implementation strategy: ingest_file_with_config copies bytes to
_external/<hash>.<ext> then delegates to existing
ingest_with_config_opts via SourceScope { root: _external/, include:
[<filename>], ... } — minimal change to existing walk pipeline.
ingest_stdin_with_config = frontmatter inject + ingest_file delegation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:49:04 +09:00
th-kim0823
7772fbc00f 📝 docs(spec): p9-fb-31 single-file / stdin ingest 설계 문서
신규 명령 `kebab ingest-file` + `kebab ingest-stdin` + MCP tool
`ingest_file` + `ingest_stdin` 도입 brainstorm 산출물. agent fetch 한
web markdown / 단일 외부 file 을 KB 에 즉시 저장.

핵심 결정:
- 외부 file 저장: copy in (`<workspace.root>/_external/<hash12>.<ext>`).
  blake3 content hash 기반 deterministic 명명 → idempotent.
- CLI: 신규 subcommand 2개 (기존 `kebab ingest` 무영향).
- MCP: 4 → 6 tool. fb-30 v1 read-only 정책 변경 — 첫 mutation tool
  surface (의도된 진화).
- .kebabignore: explicit ingest 가 default bypass + stderr warn.
- stdin v1: markdown 전용 + flag (--title, --source-uri) → frontmatter
  자동 prepend. 이미 frontmatter 있으면 error (use ingest-file).
- `_external/` 디렉토리 첫 생성 시 .kebabignore 자동 append (walk
  re-ingestion 무한 루프 방지).
- source_uri 는 frontmatter → Document.metadata 자동 흐름. wire
  schema 변경 없음 (ingest_report.v1 / search_hit.v1 의 metadata
  free-form map 재사용).

릴리스: 0.3.1 → 0.3.2 patch — additive only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:29:30 +09:00
th-kim0823
f758d51a01 📝 docs: sync README / HANDOFF / CLAUDE / skill / design for fb-30
- 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>
2026-05-07 16:15:19 +09:00
th-kim0823
72855df98b 📝 docs(plan): p9-fb-30 MCP server implementation plan
14-task plan covering:
- error_classify → kebab-app::error_wire promotion (Task 1)
- new crate kebab-mcp scaffold (Task 2)
- KebabHandler skeleton + initialize (Task 3)
- 4 tool wire-up: schema / doctor / search / ask (Tasks 4-7)
- error mapping test (Task 8)
- tools/list integration (Task 9)
- kebab-cli Cmd::Mcp + spawn smoke (Task 10)
- capability flag flip (Task 11)
- doc sync (Task 12)
- HOTFIXES + status flip (Task 13)
- final workspace verification (Task 14)

rmcp 1.6 SDK 채택. plan 의 macro / extractor 시그니처는 best-effort —
실제 rmcp 1.6 API 와 다르면 Task 3 부터 hand-roll fallback 명시.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 14:54:43 +09:00
th-kim0823
58ec4578b9 📝 docs(spec): p9-fb-30 MCP server (stdio) 설계 문서
`kebab mcp` 신규 subcommand + new crate `kebab-mcp` 도입을 위한
brainstorm 산출물. agent integration "MVP" 완성 (Claude Code / Cursor /
OpenAI Agents 등 host-agnostic 사용 가능).

핵심 결정:
- `kebab mcp` subcommand (kebab-cli 내, 신규 binary 아님)
- 4 read-only tool (`search` / `ask` / `schema` / `doctor`) — ingest /
  fetch / list_docs / inspect_chunk 는 fb-31 / fb-35 / 후속에서 추가
- Resources / Prompts 모두 skip (tools only)
- Rust MCP SDK 사용 — rmcp 채택 우선, plan 단계 verify
- stdio 단일 transport — fb-29 deferral 따라 HTTP-SSE P+
- error mapping: tool dispatch 실패만 isError=true + error.v1 content,
  refusal / no-hit / unhealthy 는 정상 응답 (semantic flag 으로 분기)
- classify 모듈 이전: kebab-cli::error_classify → kebab-app::error_wire
  (kebab-cli + kebab-mcp 둘 다 동일 모듈 사용, facade 룰 준수)
- capability flag `mcp_server` false → true

릴리스: 0.3.0 → 0.4.0 minor — 신규 surface + new crate + 디자인 §10.1
변경 + capability flip 모두 trigger.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 14:44:09 +09:00
th-kim0823
bb7b1cec4b 📝 docs: sync README / HANDOFF / CLAUDE / skill / design for fb-27
- 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>
2026-05-07 12:37:40 +09:00
th-kim0823
c20da0f274 📝 docs(plan): p9-fb-27 implementation plan
17-task TDD plan covering: typed signal scaffolding (kebab-app
error_signal module), ConfigInvalid + NotIndexed typed errors, SchemaV1
struct + schema_with_config facade, count_summary helper, wire_schema +
wire_error_v1 helpers, error_classify dispatcher, Cmd::Schema CLI arm,
--json mode error.v1 emission, JSON Schema literals, doc sync.

Each task = bite-sized TDD cycle (write failing test → impl → verify
pass → commit). Final task = workspace clippy + cargo test --workspace
-j 1 + manual smoke.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 11:12:05 +09:00
th-kim0823
f01f8dfc9b 📝 docs(spec): p9-fb-27 introspection + error wire 설계 문서
`kebab schema` 신규 명령 + `error.v1` wire schema 도입을 위한 brainstorm
산출물. agent 통합 (fb-30 MCP, fb-29 daemon) 의 prerequisite — 한 번의
introspection 호출로 wire 버전 / capabilities / model versions / index
stats 를 노출하고, fatal error 가 `--json` 모드에서 stderr ndjson 으로
구조화된다.

핵심 결정:
- `kebab schema --json` 단일 명령 (정적 + 동적 통합)
- error.v1 emission 은 `--json` 모드에서만 — 비 `--json` 은 기존 stderr text 유지
- exit code 0/1/2/3 unchanged, error.v1.code 가 fine-grained 분기
- 7 code initial set (config_invalid / not_indexed / model_unreachable /
  model_not_pulled / timeout / io_error / generic) + future-additive 정책

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:58:24 +09:00
7c8f1f2637 plan(p9-fb-25): TDD implementation plan — 7 tasks
Spec → 7-step plan, TDD per task.

Tasks:
1. Drop WorkspaceCfg.include + deprecation probe in Config::from_file
   (legacy include silently ignored + 단발 tracing::warn).
2. SourceScope construction cleanup (CLI + TUI 사용 ..Default::default()).
3. init_workspace header 에 지원 형식 명시 (md / png / jpg / pdf) + 테스트.
4. IngestReport.skipped_by_extension + AggregateCounts.skipped_by_extension
   (BTreeMap, stable JSON key) + wire schema additive.
5. IngestItem.warnings 채움 (`unsupported media type: .docx` 등) +
   ext_for_skip_warning helper + asset 루프 bump.
6. CLI summary + TUI status_line render breakdown (desc 정렬, 모두).
7. Docs sync — README + HANDOFF + HOTFIXES + INDEX + per-task spec.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 11:28:11 +00:00
40ca4bf27e spec(p9-fb-25): config workspace.include 제거 + 지원 형식 가시성
도그푸딩 피드백 2026-05-05:
1. config 의 include + exclude 동시 존재가 case 4 (둘 다 매치 안 함)
   에서 의미 모호.
2. 어차피 처리 가능 형식 (md / png / jpg / pdf) 이 정해져 있으니
   사용자에게 명시 필요.

설계 핵심:

- `WorkspaceCfg.include: Vec<String>` 제거 (denylist-only). 옛 config
  의 `include = [...]` 은 silently 무시 + Config::load 가 단발
  deprecation warning emit.
- `IngestItem.warnings` 에 skip 사유 채움 (`unsupported media type:
  .docx` / `kb:// URI not yet supported`).
- `IngestReport.skipped_by_extension: BTreeMap<String, u32>` 신규
  (additive wire — release 트리거 안 됨 per CLAUDE.md). key =
  lowercase ext (`docx`, `txt`), no-ext = `<no-ext>` sentinel.
- CLI / TUI summary 에 breakdown 표시 (`90 skipped: 80 docx, 5 txt,
  5 epub`) — 모두, desc 정렬.
- README + `kebab init` config.toml 주석에 지원 형식 명시.

Spec status `planned`. 다음 단계: writing-plans skill 로 implementation
plan 작성.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 11:21:42 +00:00
6a8d155da9 plan(p9-fb-23): TDD implementation plan — 10 tasks
Spec → 10-step plan, TDD per task (failing test → impl → pass → commit).

Tasks:
1. IngestItemKind::Unchanged + IngestReport.unchanged + AggregateCounts.unchanged + wire schema additive
2. CanonicalDocument 에 last_chunker_version + last_embedding_version Option 필드 추가 + 14 callers None 채움
3. V006 migration + SQLite put/get_document round-trip 신규 컬럼
4. DocumentStore::get_asset_by_workspace_path trait + SQLite impl
5. ingest pipeline 이 CanonicalDocument 에 현 chunker/embedding version stamp (no skip yet)
6. IngestOpts { progress, cancel, force_reingest } struct + ingest_with_config_opts entry (AskOpts 패턴)
7. asset 루프 early-skip 블록 (4 조건 match → Unchanged + continue)
8. CLI --force-reingest flag
9. TUI status_line 에 unchanged=N 노출
10. docs sync — README + HANDOFF + HOTFIXES + INDEX + per-task spec

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 17:34:30 +00:00
ddec3d8a94 spec(p9-fb-23): incremental ingest — skip unchanged docs
도그푸딩 피드백: 변경/신규 doc 만 ingest, 변하지 않은 문서는 skip.

설계 핵심:

- Skip 조건 4 개 (full version cascade): blake3 checksum + parser_version
  + chunker_version + embedding_version 모두 일치 시 parse/chunk/embed/
  vector upsert 회피. 비용 dominator (fastembed) 가 변경된 / 새 doc 에만.
- SQLite V006 migration — `documents` 에 `last_chunker_version` +
  `last_embedding_version` column 추가. 기존 row NULL → 첫 ingest 강제
  재처리 (안전 default).
- `IngestItemKind::Unchanged` enum variant 신규 (기존 `Skipped` 와
  의미 분리 — `Skipped` 는 media-type 필터, `Unchanged` 는 모든 versions
  match).
- `IngestReport` + `AggregateCounts` 에 `unchanged: u32` 필드 추가.
  wire schema additive — v1 호환 유지.
- `--force-reingest` flag — skip 무시하고 강제 재처리.
- TUI status_line final 에 `unchanged=N` 노출 (p9-fb-24 status bar
  dynamic slot 자동 cascade).

Spec status `planned`. 다음 단계: writing-plans skill 로 implementation
plan 작성.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 17:27:06 +00:00
ce6e7d2bb9 plan(p9-fb-24): TDD implementation plan — 11 tasks
Spec → 11-step plan, TDD per task (failing test → impl → pass → commit).

Tasks:
1. pager module + PAGE_STEP constant (single edit point)
2. Inspect refactor — replace literal 10 with PAGE_STEP (with regression
   tests pinning behavior)
3. Ask PgUp/PgDn (mode-agnostic, follow_tail freeze)
4. Library format_doc_header (column-width math reuses format_doc_row)
5. Library header wired into render_doc_list (Layout split)
6. render_status_bar — version + pane + docs + idle (cascade structure)
7. Status bar cascade — streaming / searching / Ask conv_id branches
8. Status bar — ingest progress absorb test
9. render_root layout — drop conditional ingest row, render status +
   keys (rename render_footer → render_key_hints, delete render_ingest_status)
10. cheatsheet Ask gains PgUp/PgDn row
11. Docs sync — README + HANDOFF + HOTFIXES + INDEX + per-task spec

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 16:34:51 +00:00
0c76677131 spec(p9-fb-24): TUI status/key bar + Library header + page scroll
도그푸딩 피드백 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>
2026-05-04 16:11:17 +00:00
th-kim0823
bfdb122a80 docs(spec): component documentation design (2026-05-04)
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>
2026-05-04 14:47:28 +09:00
7f0a71b96a docs(plans): preserve p9-fb-10 InputBuffer follow-up plan
Plan was authored in the worktree branch but never committed there
(generated artifact for the subagent-driven-development flow). Worktree
removed post-merge; preserving the plan in main so future readers can
trace how the 6-task decomposition + two-stage review per task
produced PR #88.
2026-05-03 12:57:38 +00:00
c97e8e00ef feat(kebab-core + kebab-store-sqlite): p9-fb-17 chat session storage (V005)
도그푸딩 item 13/14 (multi-turn 영속화) — TUI Ask 의 "이전 대화
이어가기" + 향후 CLI `--session foo` (p9-fb-18) backing store. session
header + per-turn 두 테이블, ON DELETE CASCADE 로 reset --data-only 가
한꺼번에 wipe.

## 핵심 변경

- **SQLite V005 migration** `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(session_id, turn_index)`. 모두 `STRICT`.
- **`kebab_core::ChatSessionRepo`** trait (6 method): create_session /
  get_session / list_sessions(limit, ORDER BY updated_at DESC) /
  delete_session / append_turn / list_turns(ORDER BY turn_index ASC)
- **`kebab_core::{ChatSessionRow, ChatTurnRow}`** structs — Serialize
  + Deserialize 둘 다 (CLI / wire 출력 호환)
- **`kebab-store-sqlite::SqliteStore`** impl 신규 모듈 `chat_sessions.rs`.
  `append_turn` 이 insert + parent updated_at bump 같은 connection
  에서 처리.
- **frozen design §5** 에 §5.7a chat_sessions / chat_turns 절 신설
  (full schema + trait 메서드 6 개 명시).

## HOTFIXES (V004 → V005)

spec p9-fb-17 의 `V004__chat_sessions.sql` 가 p9-fb-19 의
`V004__kv.sql` (이미 머지) 와 refinery migration number 충돌. 무중단
정정: `V005__chat_sessions.sql` 로 시프트. schema / 동작 동일, 파일명
만 이동. HOTFIXES entry 추가.

## 테스트

- 9 신규 integration unit (create/get roundtrip, missing→None, PK
  collision error, append+list ordered, dup turn_index error,
  append bumps updated_at, delete CASCADE turns, list_sessions
  ORDER BY updated_at DESC, list_sessions LIMIT)
- workspace 전체 `cargo test --workspace --no-fail-fast -j 1` exit 0
- `cargo clippy --workspace --all-targets -- -D warnings` clean

## 문서

- frozen design §5.7a 신설
- HANDOFF: 2026-05-03 entry
- HOTFIXES: V004 → V005 rename rationale
- spec status planned → in_progress

## Out of scope

- session 검색 / 필터 UI (p9-fb-18 의 `kebab ask --session list`
  같은 admin command 가 후속)
- 다른 store backend (postgres 등) — trait 만 정의, impl 은 SQLite

unblocks p9-fb-18 (CLI session/repl).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 05:37:53 +00:00
0e408fb1b5 feat(kebab-app + kebab-store-sqlite): p9-fb-19 search LRU cache + corpus_revision
도그푸딩 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>
2026-05-03 05:01:31 +00:00
6480b463bc review(회차1): RefusalReason::LlmStreamAborted variant 추가 + 빈 줄 정리
회차 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>
2026-05-02 22:11:52 +00:00