Some checks are pending
CI / lint-and-test (push) Waiting to run
Render KB claim links in leoclean replies. Local evidence: - 13 focused tests passed. - py_compile passed for Telegram bot, both leoclean KB bridges, and KB claim routes. - ruff F,E9 passed for touched files. GitHub checks were queued at merge time, not failing.
84 lines
2.6 KiB
Python
84 lines
2.6 KiB
Python
"""Source-control checks for the Hermes leoclean KB bridge files."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import ast
|
|
import importlib.util
|
|
import re
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
BRIDGE_DIR = ROOT / "hermes-agent" / "leoclean-bin"
|
|
|
|
|
|
def test_leoclean_bridge_files_are_present_and_parseable() -> None:
|
|
cloudsql_tool = BRIDGE_DIR / "cloudsql_memory_tool.py"
|
|
vps_tool = BRIDGE_DIR / "kb_tool.py"
|
|
wrapper = BRIDGE_DIR / "teleo-kb"
|
|
|
|
assert cloudsql_tool.exists()
|
|
assert vps_tool.exists()
|
|
assert wrapper.exists()
|
|
|
|
ast.parse(cloudsql_tool.read_text())
|
|
ast.parse(vps_tool.read_text())
|
|
subprocess.run(["bash", "-n", str(wrapper)], check=True)
|
|
|
|
|
|
def test_cloudsql_wrapper_supports_expected_review_gated_commands() -> None:
|
|
wrapper_text = (BRIDGE_DIR / "teleo-kb").read_text()
|
|
cloudsql_text = (BRIDGE_DIR / "cloudsql_memory_tool.py").read_text()
|
|
|
|
for command in [
|
|
"status",
|
|
"search",
|
|
"context",
|
|
"show",
|
|
"evidence",
|
|
"edges",
|
|
"propose-core-change",
|
|
"list-proposals",
|
|
"show-proposal",
|
|
]:
|
|
assert command in wrapper_text
|
|
assert command in cloudsql_text
|
|
|
|
assert "propose-edge" not in wrapper_text
|
|
assert "kb_stage.kb_proposals" in cloudsql_text
|
|
assert "canonical apply" in cloudsql_text.lower()
|
|
|
|
|
|
def test_bridge_source_does_not_commit_raw_secret_values() -> None:
|
|
combined = "\n".join(path.read_text(errors="replace") for path in BRIDGE_DIR.iterdir() if path.is_file())
|
|
forbidden_patterns = [
|
|
r"bot\d+:[A-Za-z0-9_-]{20,}",
|
|
r"postgres://[^\\s]+:[^\\s]+@",
|
|
r"-----BEGIN [A-Z ]*PRIVATE KEY-----",
|
|
r"sk-[A-Za-z0-9]{20,}",
|
|
r"xox[baprs]-[A-Za-z0-9-]{20,}",
|
|
r"AIza[0-9A-Za-z_-]{20,}",
|
|
]
|
|
for pattern in forbidden_patterns:
|
|
assert not re.search(pattern, combined), pattern
|
|
|
|
|
|
def _load_module(path: Path):
|
|
spec = importlib.util.spec_from_file_location(path.stem, path)
|
|
assert spec and spec.loader
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def test_kb_bridges_emit_public_claim_links_for_telegram_rendering() -> None:
|
|
claim_id = "d3fb892b-3c5a-4700-9512-55e5c680eec1"
|
|
expected = f"https://dash.livingip.xyz/kb/claims/{claim_id}"
|
|
|
|
for filename in ("kb_tool.py", "cloudsql_memory_tool.py"):
|
|
module = _load_module(BRIDGE_DIR / filename)
|
|
|
|
assert module.claim_url(claim_id) == expected
|
|
assert module.markdown_claim_link(claim_id, "d3fb892b") == (
|
|
f"[`d3fb892b`]({expected})"
|
|
)
|