From 9fd05d09fe17aaeee1347b9cc35a2d6618f37304 Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 21 Sep 2026 09:37:24 +0200 Subject: [PATCH] Apply GH-DEC-2026-020 to the layer conformance checker The checker now prints VALIDATED_AGAINST and its scope on every run, including the OK line (kings-guard pattern). A12 detection widens from the key name standard_version to every key and value of INTENT.md frontmatter and layer.yaml: versioned standard:/companion: paths, companion_version, and any *_version key except schema_version. Comments and non-declaration files are not reached. Declaration unchanged; gate-house confirmed it conforms. Co-Authored-By: Claude Opus 5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 63291@bnt-lap001 Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703 --- tests/test_layer_conformance.py | 70 +++++++++++++++++++++++++ tools/check_layer_conformance.py | 89 +++++++++++++++++++++++++++----- 2 files changed, 147 insertions(+), 12 deletions(-) diff --git a/tests/test_layer_conformance.py b/tests/test_layer_conformance.py index c9d7968..ee952f9 100644 --- a/tests/test_layer_conformance.py +++ b/tests/test_layer_conformance.py @@ -1,3 +1,5 @@ +import contextlib +import io from pathlib import Path from tempfile import TemporaryDirectory import unittest @@ -66,6 +68,25 @@ class LayerDeclarationTest(unittest.TestCase): self.assertNotIn("standard_version", decl) self.assertNotIn("standard_version", layer.load_intent()) + def test_no_version_anywhere_in_either_form(self): + """GH-DEC-2026-020 / A12 r2: no version in any key or value, not only the key name.""" + decl = yaml.safe_load(layer.DECL.read_text()) + self.assertEqual(layer.declaration_versions(decl), []) + self.assertEqual(layer.declaration_versions(layer.load_intent()), []) + self.assertNotIn("companion_version", decl) + self.assertNotIn("companion_version", layer.load_intent()) + + def test_every_run_prints_version_and_scope(self): + """GH-DEC-2026-020 §4: the version lives in the run, including the OK line.""" + out = io.StringIO() + with contextlib.redirect_stdout(out): + self.assertEqual(layer.main([]), 0) + text = out.getvalue() + self.assertIn(f"validated against: {layer.VALIDATED_AGAINST}", text) + self.assertIn(f"scope: {layer.SCOPE}", text) + ok = [line for line in text.splitlines() if line.startswith("OK:")] + self.assertTrue(ok and layer.VALIDATED_AGAINST in ok[0]) + def test_vocabulary_is_the_closed_four_tokens(self): self.assertEqual(layer.LAYER_VOCABULARY, {"taxonomy", "tooling", "engine", "staff"}) @@ -158,3 +179,52 @@ class LayerCheckerFailureTest(unittest.TestCase): joined = "\n".join(errors) self.assertIn("fastapi", joined) self.assertIn("/v1/check", joined) + + def test_versioned_standard_path_is_exit_2(self): + with TemporaryDirectory() as directory: + root = Path(directory) + _write_tree(root, intent=INTENT.replace( + "standard: netkingdom-security-layer-model", + "standard: net-kingdom/canon/standards/security-layer-model_v0.7.md", + )) + code, errors, _ = layer.evaluate(root=root) + self.assertEqual(code, 2) + self.assertTrue(any("standard" in item and "v0.7" in item for item in errors)) + + def test_companion_version_is_exit_2(self): + for decl, intent in ( + ({**DECL, "companion_version": "0.2"}, INTENT), + (DECL, INTENT.replace("role: PIP\n", 'role: PIP\ncompanion_version: "0.2"\n')), + (DECL, INTENT.replace("role: PIP\n", "role: PIP\ncompanion: net-kingdom/SECURITY-COMPANION.md v0.2\n")), + ): + with TemporaryDirectory() as directory: + root = Path(directory) + _write_tree(root, decl=decl, intent=intent) + code, errors, _ = layer.evaluate(root=root) + self.assertEqual(code, 2, errors) + + def test_versioned_path_nested_in_layer_yaml_is_exit_2(self): + with TemporaryDirectory() as directory: + root = Path(directory) + _write_tree(root, decl={**DECL, "catalog_entry": {"source": "canon/standards/security-layer-model_v0.8.md"}}) + code, errors, _ = layer.evaluate(root=root) + self.assertEqual(code, 2) + + def test_schema_version_and_comments_are_not_reached(self): + with TemporaryDirectory() as directory: + root = Path(directory) + _write_tree(root, decl={**DECL, "schema_version": "0.1"}) + path = root / "layer.yaml" + path.write_text("# Framework: security-layer-model_v0.7.md\n" + path.read_text()) + code, errors, _ = layer.evaluate(root=root) + self.assertEqual(code, 0, errors) + + def test_non_declaration_files_are_not_read(self): + """GH-DEC-2026-020 §3: stance/claims/classification maps keep their versions.""" + with TemporaryDirectory() as directory: + root = Path(directory) + _write_tree(root) + (root / "pep-stance.yaml").write_text('standard_version: "0.7"\n') + (root / "pip-claims.yaml").write_text('standard_version: "0.7"\n') + code, errors, _ = layer.evaluate(root=root) + self.assertEqual(code, 0, errors) diff --git a/tools/check_layer_conformance.py b/tools/check_layer_conformance.py index 3a70383..dc60052 100644 --- a/tools/check_layer_conformance.py +++ b/tools/check_layer_conformance.py @@ -16,7 +16,16 @@ Per GH-DEC-2026-017 (amendments A9, A11, A12): INTENT.md governs and layer.yaml is a derived artifact that must be marked derived and name INTENT.md as its source; layer values are compared against §3's closed four-token vocabulary after an ASCII case-fold, and neither form is -re-spelled; neither form carries a standard_version. +re-spelled; neither form carries a standard version. + +Per GH-DEC-2026-020 (A12 r2), "carries a standard version" is a property of +the content, not of a key name. The declaration is every key and value of the +INTENT.md frontmatter and of layer.yaml; a version-bearing `standard:` or +`companion:` path, a `companion_version`, or any `*_version` key other than +`schema_version` is a pin and fails. Comments and `schema_version` are not +reached. Stance, claims, and evidence-classification maps are not +declarations and are never read here. The version belongs to the run: every +run prints VALIDATED_AGAINST and the scope it ranged over. The failure it exists to catch is a *convenience* — a live lookup, an OpenBao client, or an /authorize helper "just for this consumer". That is @@ -32,6 +41,7 @@ from __future__ import annotations import argparse import ast +import re import sys from datetime import date from pathlib import Path @@ -44,6 +54,25 @@ TOOLS = ROOT / "tools" DECL = ROOT / "layer.yaml" INTENT = ROOT / "INTENT.md" +# The standard text this checker was built and validated against. A +# declaration carries no version (A12 r2); the run states it instead +# (GH-DEC-2026-020 §4). Bump when re-validated against a newer accepted text. +VALIDATED_AGAINST = "net-kingdom/canon/standards/security-layer-model_v0.7.md" + +# What a run ranges over. Nothing else in the tree is read; in particular no +# stance, claims, or evidence-classification map (GH-DEC-2026-020 §3). +SCOPE = "INTENT.md frontmatter, layer.yaml (A12 across all keys and values), tools/**/*.py" + +# A12 r2: keys that are version pins. schema_version is the file format's own +# version and is not reached. +VERSION_KEY = re.compile(r"(^|_)version$", re.IGNORECASE) +NOT_REACHED_KEYS = {"schema_version"} +# A version in a path (`..._v0.7.md`, `...-v1.md`) anywhere in a value. +VERSIONED_PATH = re.compile(r"[_-]v\d+(\.\d+)*(\.[A-Za-z]+)?\b", re.IGNORECASE) +# A bare version token (`v0.2`, `0.7`) in the value of a standard/companion pin. +PIN_KEYS = {"standard", "companion", "framework"} +VERSION_TOKEN = re.compile(r"\bv?\d+\.\d+(\.\d+)*\b", re.IGNORECASE) + TOOLING_IMPORTS = { "hvac": "OpenBao / Vault client", "bao": "OpenBao client", @@ -117,11 +146,7 @@ def load_declaration(path: Path = DECL) -> dict[str, Any]: raise ConformanceError( f"{path.name} derives from {data['derived_from']!r}; §11 names INTENT.md" ) - if "standard_version" in data: - raise ConformanceError( - f"{path.name} carries 'standard_version'; a layer declaration MUST NOT " - "(GH-DEC-2026-017 §5, A12)" - ) + _reject_versions(path.name, data) return dict(data) @@ -131,14 +156,48 @@ def load_intent(path: Path = INTENT) -> dict[str, Any]: front = _frontmatter(path) if "layer" not in front: raise ConformanceError("INTENT.md frontmatter has no 'layer:' key (§11)") - if "standard_version" in front: - raise ConformanceError( - "INTENT.md frontmatter carries 'standard_version'; a layer declaration " - "MUST NOT (GH-DEC-2026-017 §5, A12)" - ) + _reject_versions("INTENT.md frontmatter", front) return front +def declaration_versions(data: Any, where: str = "") -> list[str]: + """Every standard/companion version pin in a declaration (A12 r2). + + Walks all keys and values. Comments never reach here (YAML drops them); + schema_version is skipped by name. + """ + found: list[str] = [] + if isinstance(data, Mapping): + for key, value in data.items(): + name = str(key) + here = f"{where}.{name}" if where else name + if name.lower() in NOT_REACHED_KEYS: + continue + if VERSION_KEY.search(name): + found.append(f"key '{here}' is a version pin") + continue + if name.lower() in PIN_KEYS and isinstance(value, (str, int, float)): + if VERSION_TOKEN.search(str(value)) or VERSIONED_PATH.search(str(value)): + found.append(f"'{here}: {value}' carries a version") + continue + found.extend(declaration_versions(value, here)) + elif isinstance(data, list): + for index, item in enumerate(data): + found.extend(declaration_versions(item, f"{where}[{index}]")) + elif isinstance(data, str) and VERSIONED_PATH.search(data): + found.append(f"'{where}: {data}' is a version-bearing path") + return found + + +def _reject_versions(source: str, data: Any) -> None: + hits = declaration_versions(data) + if hits: + raise ConformanceError( + f"{source} carries a standard version; a layer declaration MUST NOT, in any " + f"key or value (GH-DEC-2026-017 §5, GH-DEC-2026-020, A12 r2): " + "; ".join(hits) + ) + + def _norm(value: Any) -> str: """ASCII case-fold (§3 as amended by A9). Only A-Z are folded.""" text = str(value or "").strip() @@ -294,6 +353,8 @@ def main(argv: Iterable[str] | None = None) -> int: args = parser.parse_args(list(argv) if argv is not None else None) code, errors, reports = evaluate() + print(f"checker validated against: {VALIDATED_AGAINST}") + print(f"scope: {SCOPE}") if args.report: try: decl = load_declaration() @@ -323,7 +384,11 @@ def main(argv: Iterable[str] | None = None) -> int: print(" Do not declare it to make the check pass.", file=sys.stderr) return 1 if not args.report: - print(f"OK: Engine/PIP declaration agrees with INTENT.md; no Tooling client or decision surface in {TOOLS.relative_to(ROOT)}") + print( + "OK: Engine/PIP declaration agrees with INTENT.md and carries no standard " + f"version; no Tooling client or decision surface in {TOOLS.relative_to(ROOT)}; " + f"validated against {VALIDATED_AGAINST}" + ) return 0