PR-A 본체. plan Task A4 Step 1c + A5. - lexical.rs::build_match_string 재설계: whole-phrase + token-AND OR-combined, 3자 미만 토큰 drop, 후보 없음 시 None (빈 MATCH 회피). raw single-quote mode 유지. - SearchResponse.hint additive — empty result + trimmed < 3 chars + non-raw 케이스에 short_query_hint helper 가 set. - CLI 'kebab search' 가 [hint] stderr 한 줄 (text mode). - TUI SearchState.short_query_hint + poll_worker stale-aware set + fire_search/mark_input_changed reset + dynamic_status 표시. - docs/wire-schema/v1/search_response.schema.json hint additive. - 신규 unit tests (lexical 9 PASS, 기존 2 expectation 갱신) + 통합 회귀 (search_korean: multi_token + mixed, 3 PASS) + BM25 snapshot regen (trigram token stream). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
39 lines
2.5 KiB
JSON
39 lines
2.5 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://kb.local/wire/v1/search_response.schema.json",
|
|
"title": "SearchResponse v1",
|
|
"description": "Top-level wrapper for `kebab search --json` output. Replaces the bare `search_hit.v1[]` array — wraps it with pagination + truncation metadata. Token counts are approximate (chars/4 estimate, no tokenizer dep). On `truncated: true`, caller may either widen `--max-tokens` or follow `next_cursor` for the next page. Stale `next_cursor` (corpus_revision changed since issued) returns `error.v1.code = stale_cursor`.",
|
|
"type": "object",
|
|
"required": ["schema_version", "hits", "next_cursor", "truncated"],
|
|
"properties": {
|
|
"schema_version": { "const": "search_response.v1" },
|
|
"hits": { "type": "array", "description": "search_hit.v1[]" },
|
|
"next_cursor": { "type": ["string", "null"], "description": "Opaque base64 cursor for next page; null when no more hits." },
|
|
"truncated": { "type": "boolean", "description": "True when budget forced snippet shortening or k reduction. Independent of `next_cursor`: caller may widen `max_tokens` (re-issue same query) or follow `next_cursor` (advance through more hits) or both." },
|
|
"trace": {
|
|
"type": "object",
|
|
"description": "p9-fb-37: present iff caller passed --trace / SearchOpts.trace=true. Lex/vec pre-fusion lists + RRF union + per-stage timing.",
|
|
"required": ["lexical", "vector", "rrf_inputs", "timing"],
|
|
"properties": {
|
|
"lexical": { "type": "array", "items": { "type": "object" } },
|
|
"vector": { "type": "array", "items": { "type": "object" } },
|
|
"rrf_inputs":{ "type": "array", "items": { "type": "object" } },
|
|
"timing": {
|
|
"type": "object",
|
|
"required": ["lexical_ms", "vector_ms", "fusion_ms", "total_ms"],
|
|
"properties": {
|
|
"lexical_ms": { "type": "integer", "minimum": 0 },
|
|
"vector_ms": { "type": "integer", "minimum": 0 },
|
|
"fusion_ms": { "type": "integer", "minimum": 0 },
|
|
"total_ms": { "type": "integer", "minimum": 0 }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"hint": {
|
|
"type": "string",
|
|
"description": "v0.17.0 A5 Step 4b: advisory string set when the empty hit list is likely due to a query shorter than the FTS5 trigram tokenizer's 3-char minimum. Field is omitted when no advisory applies. Raw FTS5 mode ('...') opts out. MCP / agent consumers should surface this so users understand the empty result rather than retrying the same short query."
|
|
}
|
|
}
|
|
}
|