Apply GH-DEC-2026-021: name the text in force, converge on the reference detector

VALIDATED_AGAINST now names the accepted security-layer-model v0.7
(net-kingdom@66dc491) as amended by GH-DEC-2026-017, -020, -021
(gate-house@39d9287), not the held v0.8 (021 §2).

The A12 detector converges on ops-warden's playbook reference plus the
021 §3 addition (a version in a standard:/companion: value is a pin).
A prose citation such as 'the v0.7 scope rule' is no longer failed
(021 §1); tests updated. The layer.yaml note rewording stays.

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 13:05:05 +02:00
parent 8322f0587e
commit ff0712b260
2 changed files with 43 additions and 30 deletions

View file

@ -7,8 +7,8 @@ Read-only. Makes two mechanical checks:
derived artifact (derived: true, derived_from: INTENT.md) that must agree
with it after ASCII case-folding. The layer is one of §3's closed four
tokens (Taxonomy, Tooling, Engine, Staff). Neither form carries a
version of the standard or its companion in any key or value
(GH-DEC-2026-017 §1-§5, GH-DEC-2026-020, amendments A9, A11, A12 r2).
version of the standard or its companion as a pin (GH-DEC-2026-017
§1-§5, GH-DEC-2026-020, GH-DEC-2026-021 §1, amendments A9, A11, A12 r2).
2. No catalogued Tooling client (OpenBao, key-cape) appears in src/
unless it maps to a declared §5.1 / §5.2 / §5.3 entry.
@ -16,10 +16,13 @@ PostgreSQL / SQLite / httpx-to-flex-auth / httpx-to-audit-core are not
Tooling contacts. They are listed in layer.yaml non_tooling_clients so
the inventory is total.
A12 r2 reaches content, not a key name: a `*_version` key (standard_version,
companion_version, ...), a versioned `security-layer-model_v0.7.md` or
companion path, and a bare `v0.7` token all count. `schema_version` and YAML
comments are not reached. Stance, claims and classification maps
A12 reaches a pin, not a citation (GH-DEC-2026-021 §1). The detector is
ops-warden's estate reference (wiki/playbooks/netkingdom-layer-declaration.md,
021 §3): a key naming a standard or companion version, a version in a path or
file-name token (`_v0.7`, `-v0.8.md`, `@0.7`), and, the one addition, any
version token in the value of a `standard:` or `companion:` key. A revision
cited in prose (a space-preceded `v0.7`) is provenance and is not reached.
`schema_version` and YAML comments are not reached. Stance, claims and classification maps
(pep-stance.yaml, pip-claims.yaml) are not declarations; this check does not
read them for A12 and must not (A12 r2, GH-DEC-2026-020 §3).
@ -41,34 +44,33 @@ try:
import yaml
except ImportError: # pragma: no cover - dev extra
print("FAIL: PyYAML is required (pip install pyyaml)", file=sys.stderr)
raise SystemExit(2)
raise SystemExit(2) from None
ROOT = Path(__file__).resolve().parents[1]
SRC = ROOT / "src" / "tenant_engine"
DECL = ROOT / "layer.yaml"
INTENT = ROOT / "INTENT.md"
# The standard text this checker was built and validated against
# (GH-DEC-2026-020 §4, A12 r2: the version belongs to the run). Bump it when
# the checker is re-validated against a newer accepted text.
VALIDATED_AGAINST = ("net-kingdom/canon/standards/security-layer-model_v0.8.md "
"@ net-kingdom f9e1611, with gate-house "
"docs/amendments/v0.8-section-11-declaration-amendments.md "
"A9, A11, A12 r2 @ gate-house 104f3fc")
# The text in force this checker enforces (GH-DEC-2026-020 §4, GH-DEC-2026-021
# §2): the ACCEPTED v0.7 plus the gate-house decisions enforced beyond it. v0.8
# is held under GH-DEC-2026-019 and does not govern, so it is not named here.
# Re-point after the flip (GH-WP-0004-T11).
VALIDATED_AGAINST = ("net-kingdom/canon/standards/security-layer-model_v0.7.md "
"(net-kingdom@66dc491) as amended by GH-DEC-2026-017, "
"GH-DEC-2026-020, GH-DEC-2026-021 (gate-house@39d9287)")
SCOPE = ("declaration = INTENT.md frontmatter + layer.yaml (every key and value); "
"tooling scan = src/tenant_engine/**/*.py; "
"not reached: pep-stance.yaml, pip-claims.yaml, comments, schema_version")
# A12 r2: what reads as a version of this standard or its companion.
_VERSION_KEY = re.compile(r"(?:^|_)version$", re.IGNORECASE)
# A12 pin detector, converged on ops-warden's estate reference (GH-DEC-2026-021
# §3). The path pattern deliberately flags a versioned path of any document.
_VERSION_KEY = re.compile(r"(standard|companion).*version|version.*(standard|companion)",
re.IGNORECASE)
_VERSION_IN_VALUE = re.compile(r"[_\-.]v\d+(\.\d+)*(\.md)?\b|@v?\d+\.\d+", re.IGNORECASE)
_EXEMPT_KEYS = {"schema_version"} # the declaration file's own schema, not reached
_VERSIONED_PATH = re.compile(
r"(?:security-layer-model|security[-_]companion|companion)[^\s]*?[_-]v?\d+(?:\.\d+)+",
re.IGNORECASE)
# A bare version token (v0.7). A declaration names no other versioned text, so
# a bare token reads as this standard's. File-name suffixes of other
# standards (…_v0.1.md) are preceded by '_' and are not matched here.
_BARE_VERSION = re.compile(r"(?<![\w.])v\d+(?:\.\d+)+\b", re.IGNORECASE)
# 021 §3 addition: an identity-bearing standard:/companion: value carries no version.
_IDENTITY_KEYS = {"standard", "companion"}
_ANY_VERSION = re.compile(r"v?\d+\.\d+", re.IGNORECASE)
# Catalogued Tooling in statute §4 today: key-cape and OpenBao.
# Import roots that would constitute a direct client of those.
@ -94,7 +96,7 @@ def _fold(value: object) -> str:
def version_findings(data: object, where: str) -> list[str]:
"""Every key or value of a parsed declaration that carries a version (A12 r2)."""
"""Every pin in a parsed declaration (A12, GH-DEC-2026-021 §1, §3)."""
found: list[str] = []
def walk(node: object, path: str) -> None:
@ -106,14 +108,16 @@ def version_findings(data: object, where: str) -> list[str]:
if _VERSION_KEY.search(str(key)):
found.append(f"{where}: key '{sub}' is a version key")
continue
if isinstance(key, str):
walk(key, sub + " (key)")
if (_fold(key) in _IDENTITY_KEYS and isinstance(value, str)
and _ANY_VERSION.search(value)):
found.append(f"{where}: '{sub}' carries a version: {value.strip()[:80]!r}")
continue
walk(value, sub)
elif isinstance(node, list):
for i, item in enumerate(node):
walk(item, f"{path}[{i}]")
elif isinstance(node, str):
if _VERSIONED_PATH.search(node) or _BARE_VERSION.search(node):
if _VERSION_IN_VALUE.search(node):
found.append(f"{where}: '{path}' carries a version: {node.strip()[:80]!r}")
walk(data, "")
@ -124,7 +128,7 @@ def _reject_versions(data: object, where: str) -> None:
findings = version_findings(data, where)
if findings:
print("FAIL: a layer declaration must not carry a version of the standard "
"or its companion, in any key or value (A12 r2, GH-DEC-2026-020)",
"or its companion, as a pin (A12, GH-DEC-2026-020, GH-DEC-2026-021 §1)",
file=sys.stderr)
for line in findings:
print(f" {line}", file=sys.stderr)

View file

@ -85,7 +85,8 @@ def test_versioned_standard_path_or_companion_version_fails():
{**base, "companion_version": "0.2"},
{**base, "companion": "net-kingdom/SECURITY-COMPANION.md v0.2"},
{**base, "standard_version": "0.8"},
{**base, "notes": [{"note": "Outside §5 by the v0.7 scope rule."}]},
{**base, "standard": "security-layer-model v0.7"}, # 021 §3 addition
{**base, "ref": "net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md"},
]
for data in bad:
assert checker.version_findings(data, "x"), data
@ -97,10 +98,18 @@ def test_schema_version_comments_and_section_numbers_are_not_reached():
"# Framework: net-kingdom/canon/standards/security-layer-model_v0.7.md\n"
"schema_version: '0.1'\nstandard: netkingdom-security-layer-model\n"
"declared_shapes: {'5.1': [], '5.2': []}\ndeclared_at: '2026-08-29'\n"
"ref: net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md\n")
"notes: [{note: 'Outside §5 by the v0.7 scope rule.'}]\n")
assert checker.version_findings(data, "x") == []
def test_prose_citation_is_not_a_pin():
"""GH-DEC-2026-021 §1: a revision cited in prose is provenance, not reached."""
checker = _checker()
for data in ({"notes": [{"note": "Outside §5 by the v0.7 scope rule."}]},
{"role_note": "Per Security Layer Model v0.8 §11 and companion v0.2."}):
assert checker.version_findings(data, "x") == [], data
def test_checker_does_not_apply_a12_to_stance_or_claims_maps():
"""A12 r2 / GH-DEC-2026-020 §3: those files keep their version and are not read for it."""
for name in ("pep-stance.yaml", "pip-claims.yaml"):