The checker now prints the standard version and the run's scope first on every run, pass or fail, and enforces A12 r2 over every key and value of the INTENT.md frontmatter and layer.yaml, not only a key named standard_version. Tests fail if a versioned standard: path or a companion_version comes back. Neither declaration form changed. KG-DEC-2026-005 records assent to A9, A10, A11 and A13 and returns A12 r2 revised, with one finding: "any value" reaches prose revision citations. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 63291@bnt-lap001 Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
290 lines
11 KiB
Python
290 lines
11 KiB
Python
"""kings-guard's layer declaration is checkable, not merely asserted (§11).
|
||
|
||
The claim under test is the one our whole position rests on: no direct
|
||
Tooling-layer client. A test that only ran the checker against a clean tree
|
||
would prove nothing — it would pass just as happily if the checker were broken.
|
||
So the negative case is exercised too, on a synthetic tree.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import subprocess
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
|
||
yaml = pytest.importorskip("yaml")
|
||
|
||
ROOT = Path(__file__).resolve().parents[1]
|
||
SCRIPT = ROOT / "scripts" / "check_layer_conformance.py"
|
||
DECL = ROOT / "layer.yaml"
|
||
|
||
|
||
def _run(*args: str) -> subprocess.CompletedProcess[str]:
|
||
return subprocess.run(
|
||
[sys.executable, str(SCRIPT), *args],
|
||
capture_output=True,
|
||
text=True,
|
||
)
|
||
|
||
|
||
def test_declaration_exists_and_declares_staff():
|
||
"""§11: an estate-authored repository declares its layer machine-readably."""
|
||
assert DECL.exists(), "no layer.yaml — §11 requires a machine-readable declaration"
|
||
data = yaml.safe_load(DECL.read_text())
|
||
assert data["repository"] == "kings-guard"
|
||
# Folded, not equal: §3's vocabulary is case-insensitive (GH-DEC-2026-017 §2).
|
||
# An equality assertion here would perform the re-spelling the ruling declined.
|
||
assert data["layer"].lower() == "staff"
|
||
assert data["framework"] == "netkingdom-security-layer-model"
|
||
|
||
|
||
def _load_checker():
|
||
import importlib.util
|
||
|
||
spec = importlib.util.spec_from_file_location("check_layer_conformance", SCRIPT)
|
||
module = importlib.util.module_from_spec(spec)
|
||
spec.loader.exec_module(module)
|
||
return module
|
||
|
||
|
||
def _intent_frontmatter() -> dict:
|
||
lines = (ROOT / "INTENT.md").read_text().splitlines()
|
||
assert lines[0].strip() == "---"
|
||
end = lines[1:].index("---") + 1
|
||
return yaml.safe_load("\n".join(lines[1:end]))
|
||
|
||
|
||
def test_intent_governs_and_the_sidecar_is_marked_derived():
|
||
"""GH-DEC-2026-017 §1 / A11: INTENT.md governs; layer.yaml is derived from it."""
|
||
front = _intent_frontmatter()
|
||
assert front["layer"].lower() == "staff"
|
||
data = yaml.safe_load(DECL.read_text())
|
||
assert data["derived"] is True
|
||
assert data["derived_from"] == "INTENT.md"
|
||
|
||
|
||
def test_no_standard_version_in_either_form():
|
||
"""GH-DEC-2026-017 §5 / A12: a layer declaration carries no standard version."""
|
||
assert "standard_version" not in _intent_frontmatter()
|
||
assert "standard_version" not in yaml.safe_load(DECL.read_text())
|
||
# The validated-against version moved to the conformance record, not away.
|
||
assert _load_checker().VALIDATED_AGAINST.startswith(
|
||
"net-kingdom/canon/standards/security-layer-model"
|
||
)
|
||
|
||
|
||
def test_no_version_anywhere_in_either_form():
|
||
"""A12 r2 / GH-DEC-2026-020 §1–§2: content, not a key name.
|
||
|
||
Fails if a versioned `standard:` path or a `companion_version` comes back, or
|
||
any other version pin in any key or value of either declaration form.
|
||
"""
|
||
module = _load_checker()
|
||
front = _intent_frontmatter()
|
||
assert "companion_version" not in front
|
||
assert "companion_version" not in yaml.safe_load(DECL.read_text())
|
||
assert "_v0" not in str(front.get("standard", ""))
|
||
assert module.a12_findings(front, "INTENT.md")[0] == []
|
||
assert module.a12_findings(yaml.safe_load(DECL.read_text()), "layer.yaml")[0] == []
|
||
|
||
|
||
@pytest.mark.parametrize(
|
||
"front_extra",
|
||
[
|
||
"standard: net-kingdom/canon/standards/security-layer-model_v0.7.md",
|
||
"standard: security-layer-model 0.8",
|
||
"companion: net-kingdom/SECURITY-COMPANION_v0.2.md",
|
||
'companion_version: "0.2"',
|
||
'standard_version: "0.7"',
|
||
'spec_version: "0.7"',
|
||
],
|
||
)
|
||
def test_checker_rejects_a_version_pin_in_intent_frontmatter(tmp_path, monkeypatch, front_extra):
|
||
module = _load_checker()
|
||
front = {k: v for k, v in _intent_frontmatter().items() if k != "standard"}
|
||
intent = tmp_path / "INTENT.md"
|
||
intent.write_text("---\n" + yaml.safe_dump(front) + front_extra + "\n---\n\n# INTENT\n")
|
||
monkeypatch.setattr(module, "INTENT", intent)
|
||
with pytest.raises(SystemExit) as exc:
|
||
module.load_governing_layer()
|
||
assert exc.value.code == 2
|
||
|
||
|
||
def test_checker_rejects_companion_version_in_the_sidecar(tmp_path, monkeypatch):
|
||
module = _load_checker()
|
||
decl = tmp_path / "layer.yaml"
|
||
decl.write_text(DECL.read_text() + '\ncompanion_version: "0.2"\n')
|
||
monkeypatch.setattr(module, "DECL", decl)
|
||
monkeypatch.setattr(module, "ROOT", tmp_path)
|
||
with pytest.raises(SystemExit) as exc:
|
||
module.load_declaration()
|
||
assert exc.value.code == 2
|
||
|
||
|
||
def test_schema_version_and_comments_are_not_reached():
|
||
"""GH-DEC-2026-020 §1: the sidecar's own schema version is not the standard's."""
|
||
module = _load_checker()
|
||
pins, _ = module.a12_findings(
|
||
yaml.safe_load('# Framework: security-layer-model_v0.7.md\nschema_version: "0.1"\n'),
|
||
"x",
|
||
)
|
||
assert pins == []
|
||
|
||
|
||
def test_a_prose_citation_is_reported_not_failed():
|
||
"""A revision citation in a gap record is provenance; its reach is unruled."""
|
||
module = _load_checker()
|
||
pins, citations = module.a12_findings({"owner_status": "declined (v0.6 §13)"}, "x")
|
||
assert pins == [] and citations
|
||
|
||
|
||
def test_every_run_prints_version_and_scope_even_when_it_fails(tmp_path):
|
||
"""GH-DEC-2026-020 §4: the version belongs to the run, and so does the scope."""
|
||
module = _load_checker()
|
||
ok = _run()
|
||
assert module.VALIDATED_AGAINST in ok.stdout and module.SCOPE in ok.stdout
|
||
ok_line = [line for line in ok.stdout.splitlines() if line.startswith("OK:")][0]
|
||
assert module.VALIDATED_AGAINST in ok_line and module.SCOPE in ok_line
|
||
report = _run("--report")
|
||
assert module.VALIDATED_AGAINST in report.stdout and module.SCOPE in report.stdout
|
||
# A failing run: copy the checker beside a declaration carrying a pin.
|
||
(tmp_path / "scripts").mkdir()
|
||
(tmp_path / "scripts" / SCRIPT.name).write_text(SCRIPT.read_text())
|
||
(tmp_path / "INTENT.md").write_text(
|
||
"---\nlayer: Staff\nstandard: security-layer-model_v0.7.md\n---\n"
|
||
)
|
||
failed = subprocess.run(
|
||
[sys.executable, str(tmp_path / "scripts" / SCRIPT.name)],
|
||
capture_output=True,
|
||
text=True,
|
||
)
|
||
assert failed.returncode == 2
|
||
assert module.VALIDATED_AGAINST in failed.stdout and module.SCOPE in failed.stdout
|
||
|
||
|
||
def test_the_two_forms_agree_after_folding_case():
|
||
"""`Staff` in INTENT.md and `staff` in layer.yaml are one value, not a finding."""
|
||
module = _load_checker()
|
||
front = _intent_frontmatter()
|
||
data = yaml.safe_load(DECL.read_text())
|
||
assert not module.forms_disagree(front["layer"], data["layer"])
|
||
assert not module.forms_disagree("Staff", "STAFF")
|
||
|
||
|
||
def test_a_real_layer_disagreement_survives_the_fold():
|
||
"""The fold must not blind the check: Staff vs Engine is still a finding."""
|
||
module = _load_checker()
|
||
assert module.forms_disagree("Staff", "engine")
|
||
|
||
|
||
def test_vocabulary_is_the_four_tokens_including_taxonomy():
|
||
"""A9: closed at four tokens; a three-token validator carries the defect."""
|
||
assert _load_checker().LAYER_VOCABULARY == {"taxonomy", "tooling", "engine", "staff"}
|
||
|
||
|
||
def test_checker_rejects_a_declaration_carrying_a_standard_version(tmp_path, monkeypatch):
|
||
module = _load_checker()
|
||
decl = tmp_path / "layer.yaml"
|
||
decl.write_text(DECL.read_text() + '\nstandard_version: "0.7"\n')
|
||
monkeypatch.setattr(module, "DECL", decl)
|
||
monkeypatch.setattr(module, "ROOT", tmp_path)
|
||
with pytest.raises(SystemExit) as exc:
|
||
module.load_declaration()
|
||
assert exc.value.code == 2
|
||
|
||
|
||
def test_checker_rejects_an_unmarked_sidecar(tmp_path, monkeypatch):
|
||
module = _load_checker()
|
||
data = yaml.safe_load(DECL.read_text())
|
||
data.pop("derived")
|
||
decl = tmp_path / "layer.yaml"
|
||
decl.write_text(yaml.safe_dump(data))
|
||
monkeypatch.setattr(module, "DECL", decl)
|
||
monkeypatch.setattr(module, "ROOT", tmp_path)
|
||
with pytest.raises(SystemExit) as exc:
|
||
module.load_declaration()
|
||
assert exc.value.code == 2
|
||
|
||
|
||
def test_no_tooling_contacts_declared():
|
||
"""The blocked-clean position: nothing to declare, because nothing is touched."""
|
||
data = yaml.safe_load(DECL.read_text())
|
||
assert data["tooling_contacts"] == [], (
|
||
"a Tooling contact appeared in the declaration; kings-guard's blocked-clean "
|
||
"position under §11 no longer holds and KG-DEC-2026-001 needs revisiting"
|
||
)
|
||
for shape, entries in data["declared_shapes"].items():
|
||
assert entries == [], f"§5.{shape} shape declared; see comment above"
|
||
|
||
|
||
def test_unowned_capabilities_carry_the_gap_record_fields():
|
||
"""§5.3 field shape, reused for §13 unowned-capability rows (§17 gap-record)."""
|
||
data = yaml.safe_load(DECL.read_text())
|
||
caps = data["unowned_capabilities"]
|
||
assert caps, "the three known gaps should be declared"
|
||
for cap in caps:
|
||
for field in ("capability", "intended_owner", "blocked_on", "review", "state"):
|
||
assert cap.get(field), f"{cap.get('id')} missing '{field}'"
|
||
assert cap["state"] == "unowned-capability"
|
||
|
||
|
||
def test_checker_passes_on_the_real_tree():
|
||
result = _run()
|
||
assert result.returncode == 0, result.stderr
|
||
|
||
|
||
def test_agent_principal_rule_checks_are_honest():
|
||
"""§3.4 claims that are tests, and claims that remain assertions, are named."""
|
||
data = yaml.safe_load(DECL.read_text())
|
||
checks = data["agent_principal_rule_checks"]
|
||
assert checks["no_standing_credential"]["form"] == "test"
|
||
assert checks["memory_is_not_a_state_plane"]["form"] == "test"
|
||
assert checks["tool_use_shapes"]["form"] == "assertion"
|
||
assert checks["reconstructable_as_caller"]["form"] == "mixed"
|
||
assert data["agent_principal_rules"]["no_standing_credential"] is True
|
||
|
||
|
||
def test_checker_catches_a_standing_credential(tmp_path, monkeypatch):
|
||
import importlib.util
|
||
|
||
spec = importlib.util.spec_from_file_location("check_layer_conformance", SCRIPT)
|
||
module = importlib.util.module_from_spec(spec)
|
||
spec.loader.exec_module(module)
|
||
|
||
fake_src = tmp_path / "src" / "kings_guard"
|
||
fake_src.mkdir(parents=True)
|
||
(fake_src / "secrets.py").write_text('VAULT_TOKEN = "s.standing-secret"\n')
|
||
(tmp_path / ".env").write_text("OPENBAO_TOKEN=s.also-standing\n")
|
||
monkeypatch.setattr(module, "SRC", fake_src)
|
||
monkeypatch.setattr(module, "ROOT", tmp_path)
|
||
|
||
hits = module.scan_standing_credentials()
|
||
assert hits, "a standing credential was not detected — the checker is blind"
|
||
kinds = " ".join(reason for _, reason in hits)
|
||
assert "credential-shaped file" in kinds or "standing-credential" in kinds
|
||
|
||
|
||
def test_checker_catches_an_undeclared_tooling_client(tmp_path, monkeypatch):
|
||
"""The negative case: a direct OpenBao client must fail the check.
|
||
|
||
This is the convenience §6 warns about — it would arrive as one import.
|
||
"""
|
||
import importlib.util
|
||
|
||
spec = importlib.util.spec_from_file_location("check_layer_conformance", SCRIPT)
|
||
module = importlib.util.module_from_spec(spec)
|
||
spec.loader.exec_module(module)
|
||
|
||
fake_src = tmp_path / "src" / "kings_guard"
|
||
fake_src.mkdir(parents=True)
|
||
(fake_src / "effector.py").write_text(
|
||
"import hvac\n\n\ndef contain(actor):\n hvac.Client().revoke(actor)\n"
|
||
)
|
||
monkeypatch.setattr(module, "SRC", fake_src)
|
||
monkeypatch.setattr(module, "ROOT", tmp_path)
|
||
|
||
hits = module.scan()
|
||
assert hits, "a direct OpenBao client was not detected — the checker is blind"
|
||
assert hits[0][1] == "hvac"
|