diff --git a/docs/assets/tui.gif b/docs/assets/tui.gif index 7a54510..0219df9 100644 Binary files a/docs/assets/tui.gif and b/docs/assets/tui.gif differ diff --git a/src/opspilot/kb/ingestion.py b/src/opspilot/kb/ingestion.py index e3c0c9e..85258f2 100644 --- a/src/opspilot/kb/ingestion.py +++ b/src/opspilot/kb/ingestion.py @@ -133,16 +133,25 @@ class IngestStats: # ── Discovery ───────────────────────────────────────────────────────── +# kb load-dir's fixture format pairs these two reserved names next to the +# source documents they describe (the scn_* examples still mix them in one +# directory). They are metadata *about* documents, not documents: ingesting +# a doc-meta.json puts JSON boilerplate into retrieval results (#214). +_FIXTURE_SIDECARS = frozenset({"doc-meta.json", "chunks.jsonl"}) + + def discover_files(paths: Iterable[Path]) -> list[Path]: """Walk inputs to a flat list of files. Hidden files / dirs (starting with ``.``) are skipped — they're - almost always editor swap files or VCS metadata. + almost always editor swap files or VCS metadata. KB fixture sidecars + (``doc-meta.json`` / ``chunks.jsonl``) are skipped for the same + reason: they describe the corpus rather than belong to it. """ out: list[Path] = [] for p in paths: if p.is_file(): - if not p.name.startswith("."): + if not p.name.startswith(".") and p.name not in _FIXTURE_SIDECARS: out.append(p) elif p.is_dir(): for f in sorted(p.rglob("*")): @@ -150,7 +159,11 @@ def discover_files(paths: Iterable[Path]) -> list[Path]: # segment of the full path rejected the whole tree whenever an # ancestor was dot-prefixed — `ingest ../docs` and any corpus # under a hidden directory both ingested nothing, silently. - if f.is_file() and not any(part.startswith(".") for part in f.relative_to(p).parts): + if ( + f.is_file() + and f.name not in _FIXTURE_SIDECARS + and not any(part.startswith(".") for part in f.relative_to(p).parts) + ): out.append(f) return out diff --git a/tests/test_ingestion.py b/tests/test_ingestion.py index 4676d4d..01e518e 100644 --- a/tests/test_ingestion.py +++ b/tests/test_ingestion.py @@ -129,6 +129,19 @@ def test_discover_still_skips_dot_dirs_inside_the_tree(tmp_path: Path) -> None: assert {p.name for p in discover_files([tmp_path])} == {"visible.md"} +def test_discover_skips_kb_fixture_sidecars(tmp_path: Path) -> None: + """A mixed directory — the scn_* examples' layout — ingests only the documents. + + doc-meta.json / chunks.jsonl are `kb load-dir`'s input format; walking over + them with `ingest` used to put JSON metadata into retrieval results (#214). + """ + (tmp_path / "sop.md").write_text("# SOP", encoding="utf-8") + (tmp_path / "doc-meta.json").write_text("{}", encoding="utf-8") + (tmp_path / "chunks.jsonl").write_text("{}", encoding="utf-8") + assert {p.name for p in discover_files([tmp_path])} == {"sop.md"} + assert discover_files([tmp_path / "doc-meta.json"]) == [] + + # ── Single-file ingest ───────────────────────────────────────────────