Apply GH-DEC-2026-020: remove companion_version from layer.yaml

A12 r2 reaches every key and value of the declaration, including the
companion's version. The standard: path in INTENT.md was already
unversioned and is unchanged. tests/test_layer_declaration.py fails if a
version key, a versioned standard path, or companion_version returns to
the INTENT.md frontmatter or layer.yaml; schema_version and comments are
not reached. One prose citation ("the v0.5 scope rule") in a rationale
value is allowlisted by exact text and reported to gate-house as open.

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:37:12 +02:00
parent 39e3380447
commit 71ae259877
2 changed files with 99 additions and 3 deletions

View file

@ -0,0 +1,94 @@
"""A12 r2 (GH-DEC-2026-017 §5, GH-DEC-2026-020): the layer declaration carries
no version of the standard or of its companion, in any key or value.
The declaration is every key of the INTENT.md frontmatter and every key of the
derived layer.yaml. Comments and `schema_version` are not reached. Stance,
claims and classification maps are not declarations and are not checked here.
Parsed as text, not YAML: pyyaml is not a dependency of this repository, and a
skipped test would enforce nothing.
"""
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
# A version-bearing key (any key ending in `version`, except the file's own
# schema version) or a version in a value, including one carried in a path or
# file name such as `security-layer-model_v0.7.md`.
VERSION_KEY = re.compile(r"^\s*-?\s*([A-Za-z0-9_]*version)\s*:", re.IGNORECASE)
VERSION_VALUE = re.compile(r"_v\d+(\.\d+)*|\bv\d+\.\d+")
# OPEN, reported to gate-house with this repository's A12 r2 findings: a prose
# citation of a past rule inside a rationale value ("the v0.5 scope rule") is
# not a pin, but A12 r2's "no key or value" reads literally as reaching it.
# Listed here, exactly, so it stays visible and nothing else slips past.
CITATION_ALLOWLIST = {
"Progress events. Outside §5 by the v0.5 scope rule. Recorded, not",
}
def _declaration_lines(text: str) -> list[str]:
lines = []
for raw in text.splitlines():
line = raw.split(" #", 1)[0]
if line.lstrip().startswith("#") or not line.strip():
continue
lines.append(line)
return lines
def _intent_frontmatter() -> str:
text = (ROOT / "INTENT.md").read_text()
match = re.match(r"^---\n(.*?)\n---\n", text, re.DOTALL)
assert match, "INTENT.md has no frontmatter; the declaration lives there"
return match.group(1)
def _findings(name: str, text: str) -> list[str]:
found = []
for line in _declaration_lines(text):
key = VERSION_KEY.match(line)
if key and key.group(1).lower() != "schema_version":
found.append(f"{name}: version key: {line.strip()}")
elif (
not key
and VERSION_VALUE.search(line)
and line.strip() not in CITATION_ALLOWLIST
):
found.append(f"{name}: versioned value: {line.strip()}")
return found
def test_declaration_carries_no_version():
findings = _findings("INTENT.md frontmatter", _intent_frontmatter())
findings += _findings("layer.yaml", (ROOT / "layer.yaml").read_text())
assert not findings, "\n".join(findings)
def test_companion_version_absent():
assert "companion_version" not in "\n".join(
_declaration_lines((ROOT / "layer.yaml").read_text())
)
assert "companion_version" not in "\n".join(
_declaration_lines(_intent_frontmatter())
)
def test_standard_path_unversioned():
match = re.search(r"^standard:\s*(\S+)", _intent_frontmatter(), re.MULTILINE)
assert match, "INTENT.md frontmatter names no standard"
assert match.group(1) == "net-kingdom/canon/standards/security-layer-model"
def test_detector_catches_the_forms_ruled_on():
# The check must see the pin under any name, not only `standard_version`.
assert _findings("x", 'companion_version: "0.2"\n')
assert _findings("x", 'standard_version: "0.7"\n')
assert _findings(
"x", "standard: net-kingdom/canon/standards/security-layer-model_v0.7.md\n"
)
assert not _findings("x", 'schema_version: "0.1"\n')
assert not _findings("x", "# Companion: SECURITY-COMPANION.md v0.2\n")
assert not _findings("x", ' statute: "§9.4"\n "5.1": []\n')