Files
kunail0804-ComfyUI-Scene-Co…/tests/test_kb_validation_cli.py
T
d6dcabe4f7 feat(knowledge-base): add Knowledge Base validation tooling (#9) (#52)
Implement whole-Knowledge-Base validation per MASTER_SPEC §15.10, §26.4:
compiler/common/kb_validation.py (importable by the loader) plus a CLI at
scripts/validate_knowledge_base.py.

validate_knowledge_base(entries) collects every problem (never stops at the
first); each Message carries a code, the offending id, and a description:
- duplicate canonical id -> SC0005
- invalid category -> SC0008 (drawn from the shared 19-category constant)
- circular expansion (incl. self-expansion) -> SC0003, via DFS cycle detection
- duplicate alias, alias colliding with a canonical id (no chains), missing
  expansion target, and per-entry schema nonconformance (empty tags, unknown
  fields, ...) -> umbrella SC0004
Findings are deterministically ordered.

The CLI loads every *.json (array of entries) from a directory, reports invalid
JSON / non-array files as SC0004, writes JSON findings to stdout, and exits
non-zero when invalid.

Tests: a passing fixture plus a fixture per failure mode, multi-problem
reporting, determinism, and the CLI on valid/invalid/broken-JSON inputs.

Co-authored-by: kunail0804 <kunail0804@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 19:31:16 +02:00

50 lines
1.6 KiB
Python

"""Tests for the Knowledge Base validation CLI (issue #9)."""
from __future__ import annotations
import importlib.util
import json
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
SCRIPT = REPO_ROOT / "scripts" / "validate_knowledge_base.py"
def _load_cli():
spec = importlib.util.spec_from_file_location("kb_cli", SCRIPT)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module) # type: ignore[union-attr]
return module
def test_cli_passes_on_valid_kb(tmp_path, capsys) -> None:
(tmp_path / "hair.json").write_text(
json.dumps([{"id": "long_hair", "tags": ["long hair"], "category": "hair"}]),
encoding="utf-8",
)
exit_code = _load_cli().main([str(tmp_path)])
report = json.loads(capsys.readouterr().out)
assert exit_code == 0
assert report["valid"] is True
assert report["entry_count"] == 1
def test_cli_fails_on_invalid_kb(tmp_path, capsys) -> None:
(tmp_path / "bad.json").write_text(
json.dumps([{"id": "x", "tags": ["x"], "category": "nope"}]),
encoding="utf-8",
)
exit_code = _load_cli().main([str(tmp_path)])
report = json.loads(capsys.readouterr().out)
assert exit_code == 1
assert report["valid"] is False
assert any(f["code"] == "SC0008" for f in report["findings"])
def test_cli_reports_invalid_json(tmp_path, capsys) -> None:
(tmp_path / "broken.json").write_text("{not json", encoding="utf-8")
exit_code = _load_cli().main([str(tmp_path)])
report = json.loads(capsys.readouterr().out)
assert exit_code == 1
assert any(f["code"] == "SC0004" for f in report["findings"])