Skip to content

Commit 0b19f9c

Browse files
bugfix: skip lint when KB has no indexed documents (#21)
* Skip lint when knowledge base has no indexed documents
1 parent 5c103c4 commit 0b19f9c

2 files changed

Lines changed: 86 additions & 0 deletions

File tree

openkb/cli.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,17 @@ def lint(ctx, fix):
541541
from openkb.agent.linter import run_knowledge_lint
542542

543543
openkb_dir = kb_dir / ".openkb"
544+
545+
# Skip lint entirely when the KB has no indexed documents
546+
hashes_file = openkb_dir / "hashes.json"
547+
if hashes_file.exists():
548+
hashes = json.loads(hashes_file.read_text(encoding="utf-8"))
549+
else:
550+
hashes = {}
551+
if not hashes:
552+
click.echo("Nothing to lint — no documents indexed yet. Run `openkb add` first.")
553+
return
554+
544555
config = load_config(openkb_dir / "config.yaml")
545556
_setup_llm_key(kb_dir)
546557
model: str = config.get("model", DEFAULT_CONFIG["model"])

tests/test_lint_cli.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""Tests for the openkb lint CLI command."""
2+
from __future__ import annotations
3+
4+
import json
5+
from pathlib import Path
6+
from unittest.mock import patch
7+
8+
from click.testing import CliRunner
9+
10+
from openkb.cli import cli
11+
12+
13+
def _setup_kb(tmp_path: Path) -> Path:
14+
"""Create a minimal KB structure and return kb_dir."""
15+
kb_dir = tmp_path
16+
(kb_dir / "raw").mkdir()
17+
(kb_dir / "wiki" / "sources" / "images").mkdir(parents=True)
18+
(kb_dir / "wiki" / "summaries").mkdir(parents=True)
19+
(kb_dir / "wiki" / "concepts").mkdir(parents=True)
20+
(kb_dir / "wiki" / "reports").mkdir(parents=True)
21+
openkb_dir = kb_dir / ".openkb"
22+
openkb_dir.mkdir()
23+
(openkb_dir / "config.yaml").write_text("model: gpt-4o-mini\n")
24+
(openkb_dir / "hashes.json").write_text(json.dumps({}))
25+
(kb_dir / "wiki" / "index.md").write_text(
26+
"# Knowledge Base Index\n\n## Documents\n\n## Concepts\n"
27+
)
28+
return kb_dir
29+
30+
31+
class TestLintCommand:
32+
def test_lint_empty_kb_skips(self, tmp_path):
33+
"""Lint on an empty KB (no indexed docs) should exit early."""
34+
kb_dir = _setup_kb(tmp_path)
35+
runner = CliRunner()
36+
with patch("openkb.cli._find_kb_dir", return_value=kb_dir):
37+
result = runner.invoke(cli, ["lint"])
38+
assert result.exit_code == 0
39+
assert "Nothing to lint" in result.output
40+
assert "no documents indexed" in result.output
41+
# No report should be written
42+
reports = list((kb_dir / "wiki" / "reports").glob("*.md"))
43+
assert reports == []
44+
45+
def test_lint_no_hashes_file_skips(self, tmp_path):
46+
"""Lint should also skip when hashes.json doesn't exist."""
47+
kb_dir = _setup_kb(tmp_path)
48+
(kb_dir / ".openkb" / "hashes.json").unlink()
49+
runner = CliRunner()
50+
with patch("openkb.cli._find_kb_dir", return_value=kb_dir):
51+
result = runner.invoke(cli, ["lint"])
52+
assert result.exit_code == 0
53+
assert "Nothing to lint" in result.output
54+
55+
def test_lint_no_kb(self, tmp_path):
56+
runner = CliRunner()
57+
with runner.isolated_filesystem(temp_dir=tmp_path), \
58+
patch("openkb.cli._find_kb_dir", return_value=None):
59+
result = runner.invoke(cli, ["lint"])
60+
assert "No knowledge base found" in result.output
61+
62+
def test_lint_runs_when_docs_exist(self, tmp_path):
63+
"""Lint should proceed when there are indexed documents."""
64+
kb_dir = _setup_kb(tmp_path)
65+
hashes = {"abc": {"name": "paper.pdf", "type": "pdf"}}
66+
(kb_dir / ".openkb" / "hashes.json").write_text(json.dumps(hashes))
67+
runner = CliRunner()
68+
with patch("openkb.cli._find_kb_dir", return_value=kb_dir), \
69+
patch("openkb.cli._setup_llm_key"), \
70+
patch("openkb.agent.linter.run_knowledge_lint", return_value="No issues."):
71+
result = runner.invoke(cli, ["lint"])
72+
assert result.exit_code == 0
73+
assert "Running structural lint" in result.output
74+
assert "Running knowledge lint" in result.output
75+
assert "Report written to" in result.output

0 commit comments

Comments
 (0)