Apply GH-DEC-2026-020: de-version the standard path and widen the checker.
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 5s
Account journey acceptance / journeys (push) Successful in 11s

INTENT.md's standard: path drops _v0.7.md; a version inside the path is a
standard version under A12 r2. The conformance checker now rejects a
version in any key or value of INTENT.md frontmatter and layer.yaml
(standard_version, companion_version, versioned standard/companion paths),
leaves schema_version and pep-stance.yaml alone, and prints VALIDATED_AGAINST
and SCOPE on every run, following kings-guard. Tests fail if a versioned
standard: path or companion_version returns.

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:
tegwick 2026-09-21 09:36:59 +02:00
parent 2ac4a36bdd
commit 4a5c21d62b
3 changed files with 108 additions and 9 deletions

View file

@ -1,7 +1,7 @@
--- ---
layer: Engine layer: Engine
role: PIP role: PIP
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md standard: net-kingdom/canon/standards/security-layer-model
companion: net-kingdom/SECURITY-COMPANION.md companion: net-kingdom/SECURITY-COMPANION.md
declared: "2026-08-29" declared: "2026-08-29"
--- ---

View file

@ -8,12 +8,17 @@ INTENT.md frontmatter governs the layer; layer.yaml is its derived form.
The failure this exists to catch is a convenience: an OpenBao, Vault, LDAP, The failure this exists to catch is a convenience: an OpenBao, Vault, LDAP,
or cluster client arriving as one import. That is an undeclared violation. or cluster client arriving as one import. That is an undeclared violation.
Every run prints the standard text it checks against (VALIDATED_AGAINST) and
the scope it ranged over (SCOPE), on the OK line and in --report. The version
lives in the run, not in the declaration (GH-DEC-2026-020, A12 r2).
Exit 0 clean, 1 undeclared contact found, 2 declaration malformed. Exit 0 clean, 1 undeclared contact found, 2 declaration malformed.
""" """
from __future__ import annotations from __future__ import annotations
import argparse import argparse
import ast import ast
import re
import sys import sys
from pathlib import Path from pathlib import Path
@ -25,6 +30,25 @@ sys.path.insert(0, str(ROOT / "src"))
from user_engine.layer_yaml import load_mapping, load_mapping_text # noqa: E402 from user_engine.layer_yaml import load_mapping, load_mapping_text # noqa: E402
# The standard text this checker was built and validated against. The version
# belongs to the run, not to the declaration (GH-DEC-2026-020 §4, A12 r2); it is
# printed on every run. Bump it when the checker is re-validated.
VALIDATED_AGAINST = "net-kingdom/canon/standards/security-layer-model_v0.7.md"
# What every run ranges over. Stance, claims and classification maps
# (pep-stance.yaml) are not declarations and are not checked for versions
# (GH-DEC-2026-020 §3).
SCOPE = (
"declaration: INTENT.md frontmatter + layer.yaml (all keys and values); "
"imports: src/user_engine/**/*.py"
)
# A12 r2: no standard or companion version in any key or value of the
# declaration. Comments are not parsed; schema_version is not reached.
VERSION_KEY = re.compile(r"(?:^|_)version$", re.IGNORECASE)
VERSION_VALUE = re.compile(r"(?:^|[_\-/\s])v?\d+\.\d+(?:\.\d+)*(?:\.md)?(?=$|[\s/])|_v\d+", re.IGNORECASE)
UNREACHED_KEYS = {"schema_version"}
TOOLING_IMPORTS = { TOOLING_IMPORTS = {
"hvac": "OpenBao / Vault client", "hvac": "OpenBao / Vault client",
"bao": "OpenBao client", "bao": "OpenBao client",
@ -57,6 +81,39 @@ def fold(value: object) -> str:
) )
def find_versions(node: object, where: str, path: str = "") -> list[str]:
"""Every key or value in a declaration that carries a version (A12 r2)."""
found: list[str] = []
if isinstance(node, dict):
for key, value in node.items():
here = f"{path}.{key}" if path else str(key)
if str(key) in UNREACHED_KEYS:
continue
if VERSION_KEY.search(str(key)):
found.append(f"{where}: key '{here}'")
continue
found.extend(find_versions(value, where, here))
elif isinstance(node, list):
for index, item in enumerate(node):
found.extend(find_versions(item, where, f"{path}[{index}]"))
elif isinstance(node, str) and VERSION_VALUE.search(node):
found.append(f"{where}: value of '{path}' = {node!r}")
return found
def reject_versions(data: dict, where: str) -> None:
found = find_versions(data, where)
if found:
print(
"FAIL: a layer declaration MUST NOT carry a standard or companion "
"version in any key or value (GH-DEC-2026-017 §5, GH-DEC-2026-020, A12 r2)",
file=sys.stderr,
)
for item in found:
print(f" {item}", file=sys.stderr)
raise SystemExit(2)
def load_intent_layer() -> str: def load_intent_layer() -> str:
"""Return the governing `layer:` value from INTENT.md frontmatter (§11).""" """Return the governing `layer:` value from INTENT.md frontmatter (§11)."""
try: try:
@ -73,6 +130,7 @@ def load_intent_layer() -> str:
except ValueError as exc: except ValueError as exc:
print(f"FAIL: {INTENT.name} frontmatter is not parseable: {exc}", file=sys.stderr) print(f"FAIL: {INTENT.name} frontmatter is not parseable: {exc}", file=sys.stderr)
raise SystemExit(2) from exc raise SystemExit(2) from exc
reject_versions(front, f"{INTENT.name} frontmatter")
if "layer" not in front: if "layer" not in front:
print(f"FAIL: {INTENT.name} frontmatter has no 'layer:' key (§11)", file=sys.stderr) print(f"FAIL: {INTENT.name} frontmatter has no 'layer:' key (§11)", file=sys.stderr)
raise SystemExit(2) raise SystemExit(2)
@ -94,13 +152,7 @@ def load_declaration() -> dict:
if key not in data: if key not in data:
print(f"FAIL: {DECL.name} missing required key '{key}' (§11)", file=sys.stderr) print(f"FAIL: {DECL.name} missing required key '{key}' (§11)", file=sys.stderr)
raise SystemExit(2) raise SystemExit(2)
if "standard_version" in data: reject_versions(data, DECL.name)
print(
f"FAIL: {DECL.name} carries standard_version; a layer declaration "
"MUST NOT carry a standard version (GH-DEC-2026-017, A12)",
file=sys.stderr,
)
raise SystemExit(2)
if data["derived"] is not True or data["derived_from"] != "INTENT.md": if data["derived"] is not True or data["derived_from"] != "INTENT.md":
print( print(
f"FAIL: {DECL.name} must be marked derived: true, derived_from: INTENT.md " f"FAIL: {DECL.name} must be marked derived: true, derived_from: INTENT.md "
@ -192,6 +244,8 @@ def main() -> int:
f"user-engine — layer {decl['layer']}/{decl['role']} " f"user-engine — layer {decl['layer']}/{decl['role']} "
f"(derived from {decl['derived_from']})" f"(derived from {decl['derived_from']})"
) )
print(f" checked against: {VALIDATED_AGAINST}")
print(f" scope: {SCOPE}")
print(" tooling contacts declared: 0") print(" tooling contacts declared: 0")
print(f" own-store declarations: {len(own_store)}") print(f" own-store declarations: {len(own_store)}")
print(f" own-store imports: {len(own_store_hits)}") print(f" own-store imports: {len(own_store_hits)}")
@ -219,7 +273,7 @@ def main() -> int:
if not args.report: if not args.report:
print( print(
f"OK: no catalogued Tooling client in {SRC.relative_to(ROOT)} " f"OK: no catalogued Tooling client in {SRC.relative_to(ROOT)} "
"(Engine/PIP, §11)" f"(Engine/PIP, §11); checked against {VALIDATED_AGAINST}; scope: {SCOPE}"
) )
return 0 return 0

View file

@ -60,6 +60,40 @@ class LayerDeclarationTests(unittest.TestCase):
self.assertNotIn("standard_version", decl) self.assertNotIn("standard_version", decl)
self.assertNotIn("standard_version", front) self.assertNotIn("standard_version", front)
def test_intent_standard_path_is_unversioned(self):
# GH-DEC-2026-020 §1: a version inside the standard: path is a
# standard version under A12 r2; companion_version is one too (§2).
front = load_mapping_text((ROOT / "INTENT.md").read_text().split("---", 2)[1])
decl = load_mapping(LAYER)
self.assertEqual(
front["standard"], "net-kingdom/canon/standards/security-layer-model"
)
for mapping in (front, decl):
self.assertNotIn("companion_version", mapping)
module = _checker()
self.assertEqual(module.find_versions(front, "INTENT.md"), [])
self.assertEqual(module.find_versions(decl, "layer.yaml"), [])
def test_version_scan_leaves_schema_version_and_stance_alone(self):
module = _checker()
self.assertEqual(module.find_versions({"schema_version": "0.1"}, "x"), [])
self.assertNotIn("pep-stance", module.SCOPE)
# pep-stance.yaml keeps its version fields (GH-DEC-2026-020 §3).
self.assertTrue(module.find_versions(load_mapping(STANCE_FILE), "stance"))
def test_every_run_prints_version_and_scope(self):
module = _checker()
for argv in ([], ["--report"]):
result = subprocess.run(
[sys.executable, str(SCRIPT), *argv],
capture_output=True,
text=True,
cwd=ROOT,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn(module.VALIDATED_AGAINST, result.stdout)
self.assertIn(module.SCOPE, result.stdout)
def test_vocabulary_is_four_tokens_compared_after_fold(self): def test_vocabulary_is_four_tokens_compared_after_fold(self):
module = _checker() module = _checker()
self.assertEqual( self.assertEqual(
@ -74,6 +108,17 @@ class LayerDeclarationTests(unittest.TestCase):
good = load_mapping(LAYER) good = load_mapping(LAYER)
cases = { cases = {
"standard_version": dict(good, standard_version="0.7"), "standard_version": dict(good, standard_version="0.7"),
"companion_version": dict(good, companion_version="0.2"),
"versioned standard path": dict(
good,
standard="net-kingdom/canon/standards/security-layer-model_v0.7.md",
),
"versioned companion path": dict(
good, companion="net-kingdom/SECURITY-COMPANION.md v0.2"
),
"nested version key": dict(
good, catalog_entry=dict(good["catalog_entry"], standard_version="0.8")
),
"not derived": dict(good, derived=False), "not derived": dict(good, derived=False),
"divergent layer": dict(good, layer="staff"), "divergent layer": dict(good, layer="staff"),
} }