7c85de065a
chore: workspace-wide cleanup — clippy::pedantic baseline + auto-fix
...
cut PR v0.18.0 전 마지막 정리. 사용자 요청: "전체 코드베이스를 깔끔하고 알아보기 쉽게".
## Workspace lints
- `Cargo.toml` 의 `[workspace.lints.clippy]` 에 `pedantic = "warn"` (priority -1) + 의도적 allow-list 추가:
- cast_possible_truncation / cast_possible_wrap / cast_sign_loss / cast_precision_loss — ONNX i64 / hash modular reduction 등 의도적 truncation.
- doc_markdown / missing_errors_doc / missing_panics_doc — cosmetic doc style.
- too_many_lines / module_name_repetitions / must_use_candidate / needless_pass_by_value / manual_let_else / items_after_statements / similar_names — informational only.
- format_collect / match_wildcard_for_single_variants / trivially_copy_pass_by_ref / unnecessary_wraps — intentional patterns (exhaustive match, future Result variants 등).
- default_trait_access — `Foo::default()` 가 idiomatic.
- float_cmp — NLI / RRF score 의 explicit threshold 비교 의도.
- struct_excessive_bools / case_sensitive_file_extension_comparisons / naive_bytecount / ignore_without_reason — domain-specific 의도.
- format_push_string / return_self_not_must_use / match_same_arms — builder / wire-label / hot-path 패턴 보존.
- needless_continue / used_underscore_binding / nonminimal_bool / unreadable_literal / many_single_char_names / doc_link_with_quotes / assigning_clones / collapsible_str_replace / trivial_regex / elidable_lifetime_names / range_plus_one / explicit_iter_loop / implicit_hasher / ref_option — remaining low-value style.
- 각 24 crate `Cargo.toml` 에 `[lints] workspace = true` 추가.
## Auto-fix
`cargo clippy --workspace --all-targets --fix` 적용 — 128 files changed, 552 insertions / 472 deletions. 주로:
- uninlined_format_args (~18): `format!("{}", x)` → `format!("{x}")`.
- redundant_closure_for_method_calls (~33): `.map(|x| x.foo())` → `.map(T::foo)`.
- 그 외 mechanical refactor.
## 검증
- `cargo clippy --workspace --all-targets -j 1 -- -D warnings` clean (pedantic + 모든 lint group).
- `cargo test --workspace --no-fail-fast -j 1` — **1293 tests pass + 1 pre-existing flaky fail** (`kebab-mcp::tools_call_ask_multi_hop::ask_tool_routes_multi_hop_true_to_decompose_first`, HOTFIX candidate, cleanup 무관). 회귀 0.
Wire 영향: 없음.
Behavior 영향: 없음 (mechanical refactor only).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-26 03:01:58 +00:00
8a2f7affa6
feat(mcp): fb-41 PR-5 — MCP ask multi_hop arg + SKILL.md 안내
...
fb-41 multi-hop RAG 의 **PR-5** (PR-4 머지 직후). PR-4 의 CLI `--multi-hop`
flag 와 sister surface — agent (Claude Code 등 MCP host) 가 `mcp__kebab__ask`
호출 시 `multi_hop: true` 옵션 사용 가능.
설계: docs/superpowers/specs/2026-05-25-p9-fb-41-multi-hop-rag-design.md
계획: docs/superpowers/plans/2026-05-25-p9-fb-41-multi-hop-rag.md (PR-5 단락)
## MCP surface
- `crates/kebab-mcp/src/tools/ask.rs`:
- `AskInput.multi_hop: Option<bool>` 추가. JsonSchema derive 가 tools/list
에 자동 반영 — agent capability discovery 가 새 필드 인식.
- `handle()` 가 `AskOpts.multi_hop = input.multi_hop.unwrap_or(false)` —
기존 caller (필드 누락 / null) 는 single-pass 그대로.
- `crates/kebab-mcp/src/lib.rs` (tools/list):
- `ask` tool description 에 multi-hop 한 줄 (decompose → retrieve →
synthesize, 2-5× LLM cost, per-hop trace on Answer.hops).
## SKILL.md 안내
- `integrations/claude-code/kebab/SKILL.md` 의 `mcp__kebab__ask` 절:
- Input shape JSON 예제에 `multi_hop: false` 추가.
- Returns 절에 `hops` (multi-hop only) 추가.
- 신규 bullet (p9-fb-41) — opt-in 조건 / 비용 trade-off / 사용 케이스
(compound questions / prereq chains / cross-doc reasoning) /
`Answer.hops` 의 per-hop trace shape / `multi_hop_decompose_failed`
refusal 처리.
## Tests (`tests/tools_call_ask_multi_hop.rs` 신규, 2 Ollama-free pins)
- `ask_tool_routes_multi_hop_true_to_decompose_first`: dispatch
divergence 핀. invalid LLM endpoint (`http://127.0.0.1:1 `,
request_timeout_secs=2) 로 force unreachable. multi_hop=true 는
decompose 먼저 호출 → `error.v1` (code=model_unreachable) /
isError=true. multi_hop=false (single-pass) 는 empty KB 에서 retrieve
먼저 → no LLM call → `answer.v1` grounded=false / isError=false. 두
shape 의 분기가 dispatch 가 실제로 다른 path 로 라우팅됨의 증거.
- `ask_input_schema_advertises_multi_hop_field`: AskInput 의 JsonSchema
가 `multi_hop` property 노출 — MCP host capability discovery
(tools/list 의 input schema) 회귀 핀.
기존 `tools_call_ask.rs` 의 AskInput literal 도 `multi_hop: None`
추가 (struct field 추가에 따른 minimal cascade).
## 변경 없음
- `prompt_template_version` (`rag-multi-hop-v1`) — 그대로.
- TUI surface — PR-6 의 책임.
- error.v1 매핑 — PR-4 의 enum reservation 그대로 (no error_wire
promotion).
## 검증
- `cargo test -p kebab-mcp -j 1` — 신규 tools_call_ask_multi_hop 2 +
기존 ask / search / bulk_search / fetch / ingest / schema / doctor /
tools_list / initialize 등 모두 통과 (회귀 없음).
- `cargo clippy -p kebab-mcp --all-targets -j 1 -- -D warnings` clean.
- 단일 crate 직렬 build (16 GB RAM 제약).
## 다음 PR
- PR-6: TUI Ask 패널 multi-hop toggle (F2 / Ctrl-T) + hop trace render +
cheatsheet 갱신.
- v0.18.0 cut (PR-6 머지 후).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-25 09:06:28 +00:00
th-kim0823
c8e04c65e0
🏗️ refactor(kebab-mcp): fix ask tool production panic + mode default (fb-30)
...
Two issues from Task 7 review:
1. CRITICAL — call_tool "ask" arm called blocking ask handle from async
context. OllamaLanguageModel::new builds reqwest::blocking::Client
which creates+drops a tokio runtime → panic inside async. Fix:
tokio::task::spawn_blocking wrap. Also applied preemptively to
"search" arm (SqliteStore + Lance open are blocking IO too).
2. IMPORTANT — ask tool's retrieval mode hardcoded to Lexical (test
workaround for provider="none"); CLI default is Hybrid. Fix: add
`mode: Option<String>` field to AskInput, default Hybrid in handle,
test passes mode=Some("lexical") explicitly to keep test functional
on provider="none".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-07 15:55:02 +09:00
th-kim0823
4b1b8a15bf
✨ feat(kebab-mcp): ask tool (fb-30)
...
Fourth (and final v1) tool — `ask` (input: query / optional session_id).
Multi-turn via optional session_id (kebab_app::ask_with_session_with_config),
single-shot via ask_with_config when None. Refusal (grounded:false) NOT
mapped to isError — agent branches on the wire payload's grounded flag.
AskOpts has no Default impl (must construct manually). Answer carries no
schema_version field (tagged inline via entry().or_insert_with, idempotent).
Mode defaulted to Lexical: reqwest::blocking::Client::build creates and
drops a tokio runtime, panicking inside async context — the empty-corpus
refusal test avoids this via spawn_blocking; the tool itself uses Lexical
as the default mode since MCP callers typically run without an embedding
provider configured.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-07 15:50:57 +09:00