- 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>
- wire schema: relax effective_end.minimum 1 → 0 + expand
description to cover line-clamp + out-of-range sentinel
(panic-fix R1 emits Some(0) when line_start=1 and range is
beyond doc end — schema must accept it)
- tests: tighten first-chunk-target boundary test to assert ≤ 2
total neighbors (3-chunk doc, N=2). Strict "first chunk →
context_before empty" not assertable until chunks.ordinal
column lands (R1 #9 architectural caveat)
- store: trim contradiction in list_chunk_ids_for_doc warning
comment — drop "good enough for sequentially chunked
markdown" phrase that conflicts with "hash sort dominates"
paragraph above
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>
Wrapper around search_hit.v1[] with next_cursor + truncated.
Wire breaking — agent that parses bare array must adapt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- pipeline: refresh module docstring step 5 to reflect new cancel
semantics (RetrievalDone/Token/Final + LlmStreamAborted)
- wire schema: spell out refusal-path behavior in answer_event.v1
description (only retrieval_done emitted; no final)
- test: factual comment on relax_score_gate-using test corrected
- test: new Ollama-gated stream_score_gate_refusal_emits_only_retrieval_done
- test: new ask_emits_no_final_when_cancelled_mid_stream pinning
the no-Final invariant on cancel
- pipeline: large_enum_variant comment broadened to acknowledge
RetrievalDone.hits as the dominant per-emit cost
- HOTFIXES: log AskOpts.stream_sink internal API break per spec
contract policy
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Discriminated ndjson event for `kebab ask --stream`. Mirrors
the ingest_progress.v1 pattern (stderr stream + stdout final
answer.v1 for backwards compat).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
검색 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>
신규 명령 `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>
Final review fixes:
- docs/ARCHITECTURE.md: add kebab-mcp to UI subgraph + directory tree
(CLAUDE.md "add new crate" rule required this; missed in Task 12 doc sync).
- state.rs: replace forward-reference Task 10 comment with current-state
doc (config_path now wired by Task 10 commit 4a30959).
- tools_call_schema.rs: assert capabilities.mcp_server == true (already
pinned in schema_report + cli_schema, this closes the gap in mcp's own
test).
Version bump 0.3.0 → 0.4.0 deferred to separate `chore/bump-v0.4.0` PR
mirroring fb-27 precedent (commit 73f5d73 / PR #105).
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>
`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>
- 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>
schema.v1: full introspection report shape with required fields for
wire / capabilities / models / stats. capabilities object enumerates
all 10 flag names (current 6 true + future 4 false) as required keys.
error.v1: 7-code enum + permissive details object. Real emitted
details shapes documented in description (per-code context varies and
some fields are interim until IoFailure / OpTimeout typed signals
land in follow-up).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`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>