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 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 63291@bnt-lap001 Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
This commit is contained in:
parent
cd54d8e716
commit
9fd05d09fe
2 changed files with 147 additions and 12 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue