docs(fb-37): wire schema + README + SMOKE + INDEX + SKILL

This commit is contained in:
th-kim0823
2026-05-10 14:04:54 +09:00
parent 5687cbc0e2
commit a40593590b
8 changed files with 74 additions and 9 deletions

View File

@@ -206,6 +206,22 @@ kebab search "rust" --doc-id "<doc-id>" --tag rust --json
Bad `--ingested-after` → `error.v1.code = config_invalid`, exit 2.
Unknown `--media` value → silently empty (no error).
### Trace + stats (fb-37)
Re-run a search with `--trace` to see per-stage candidate lists + timing:
```bash
kebab --config /tmp/kebab-smoke/config.toml search "rust async" --trace --json | jq .trace
```
Inspect the corpus health surface:
```bash
kebab --config /tmp/kebab-smoke/config.toml schema --json | jq .stats
```
Look for: `media_breakdown` (5 keys), `lang_breakdown`, `index_bytes`, `stale_doc_count`.
## P6-4 이미지 ingestion 옵션
`config.toml` 에 다음 절을 추가하면 `kebab ingest` 가 `**/*.png` / `**/*.jpg` 등 이미지 자산도 함께 색인합니다 (텍스트만 색인하려면 생략):

View File

@@ -54,6 +54,30 @@
{ "type": "string", "format": "date-time" },
{ "type": "null" }
]
},
"media_breakdown": {
"type": "object",
"description": "p9-fb-37: per-media-kind doc count. 5 keys (markdown/pdf/image/audio/other), zero-padded.",
"additionalProperties": { "type": "integer", "minimum": 0 }
},
"lang_breakdown": {
"type": "object",
"description": "p9-fb-37: per-language doc count. NULL lang keyed as the literal string 'null'. Map may be empty on empty corpus.",
"additionalProperties": { "type": "integer", "minimum": 0 }
},
"index_bytes": {
"type": "object",
"description": "p9-fb-37: on-disk byte sums.",
"required": ["sqlite", "lancedb"],
"properties": {
"sqlite": { "type": "integer", "minimum": 0 },
"lancedb": { "type": "integer", "minimum": 0 }
}
},
"stale_doc_count": {
"type": "integer",
"minimum": 0,
"description": "p9-fb-37: docs whose updated_at exceeds config.search.stale_threshold_days. 0 when threshold=0."
}
}
}

View File

@@ -9,6 +9,26 @@
"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." }
"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 }
}
}
}
}
}
}