Run structural + knowledge lint, write report, return report path. Returns ``None`` if the KB has no indexed documents (nothing to lint). Async because knowledge lint uses an LLM agent. Usable from CLI (via ``asyncio.run``) and directly from the chat REPL.
(kb_dir: Path)
| 1857 | |
| 1858 | |
| 1859 | async def run_lint(kb_dir: Path) -> Path | None: |
| 1860 | """Run structural + knowledge lint, write report, return report path. |
| 1861 | |
| 1862 | Returns ``None`` if the KB has no indexed documents (nothing to lint). |
| 1863 | Async because knowledge lint uses an LLM agent. Usable from CLI |
| 1864 | (via ``asyncio.run``) and directly from the chat REPL. |
| 1865 | """ |
| 1866 | from openkb.lint import run_structural_lint |
| 1867 | from openkb.agent.linter import run_knowledge_lint |
| 1868 | |
| 1869 | openkb_dir = kb_dir / ".openkb" |
| 1870 | |
| 1871 | with kb_read_lock(openkb_dir): |
| 1872 | # Skip lint entirely when the KB has no indexed documents |
| 1873 | hashes_file = openkb_dir / "hashes.json" |
| 1874 | if hashes_file.exists(): |
| 1875 | hashes = json.loads(hashes_file.read_text(encoding="utf-8")) |
| 1876 | else: |
| 1877 | hashes = {} |
| 1878 | if not hashes: |
| 1879 | click.echo("Nothing to lint — no documents indexed yet. Run `openkb add` first.") |
| 1880 | return |
| 1881 | |
| 1882 | config = load_config(openkb_dir / "config.yaml") |
| 1883 | _setup_llm_key(kb_dir) |
| 1884 | model: str = config.get("model", DEFAULT_CONFIG["model"]) |
| 1885 | |
| 1886 | click.echo("Running structural lint...") |
| 1887 | structural_report = run_structural_lint(kb_dir) |
| 1888 | click.echo(structural_report) |
| 1889 | |
| 1890 | click.echo("Running knowledge lint...") |
| 1891 | try: |
| 1892 | knowledge_report = await run_knowledge_lint(kb_dir, model) |
| 1893 | except Exception as exc: |
| 1894 | knowledge_report = f"Knowledge lint failed: {exc}" |
| 1895 | click.echo(knowledge_report) |
| 1896 | |
| 1897 | # Write combined report |
| 1898 | with kb_ingest_lock(openkb_dir): |
| 1899 | reports_dir = kb_dir / "wiki" / "reports" |
| 1900 | reports_dir.mkdir(parents=True, exist_ok=True) |
| 1901 | import datetime |
| 1902 | |
| 1903 | timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") |
| 1904 | report_path = reports_dir / f"lint_{timestamp}.md" |
| 1905 | report_content = f"# Lint Report — {timestamp}\n\n## Structural\n\n{structural_report}\n\n## Semantic\n\n{knowledge_report}\n" |
| 1906 | report_path.write_text(report_content, encoding="utf-8") |
| 1907 | append_log(kb_dir / "wiki", "lint", f"report → {report_path.name}") |
| 1908 | click.echo(f"\nReport written to {report_path}") |
| 1909 | return report_path |
| 1910 | |
| 1911 | |
| 1912 | @cli.command() |
no test coverage detected