Record exact layer review and migrate checker to accepted v0.8

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
This commit is contained in:
tegwick 2026-10-11 02:21:40 +02:00
parent 0d58f14a7a
commit cdaa828ee9
6 changed files with 196 additions and 19 deletions

View file

@ -23,8 +23,8 @@ case against §3's closed four-token vocabulary, so `Staff` and `staff` agree an
neither file is re-spelled. A disagreement that survives the fold is reported as
a finding, not resolved by precedence. Neither form may carry a version of the
standard or its companion in any key or value (A12 r2, GH-DEC-2026-020 §1–§2):
not only a key named `standard_version`, but `companion_version`, any other
version key, and a version-bearing path or file name such as a `standard:` of
not only a key named `standard_version`, but `companion_version`, another
key naming a standard/companion version, and a version-bearing path or file name such as a `standard:` of
`…security-layer-model_v0.7.md`. Comments are not read (YAML drops them) and
`schema_version` is the sidecar's own schema, so neither is reached. Only
INTENT.md frontmatter and layer.yaml are read for A12: stance, claims and
@ -32,9 +32,8 @@ classification maps are not declarations and this run never applies A12 to them
(GH-DEC-2026-020 §3).
A bare revision citation in a prose value — `layer.yaml` cites "v0.6 §13" as
provenance in a gap record — is reported on every run, not failed: whether A12 r2's
"any value" reaches a citation rather than a pin is raised with gate-house by
kings-guard (see decisions/decisions.md KG-DEC-2026-005), not settled here.
provenance in a gap record — is reported on every run, not failed. A12 r3
excludes prose provenance from declaration pins.
Every run prints, first, the standard version this check was built and validated
against (VALIDATED_AGAINST) and the scope it ranges over (SCOPE), including runs
@ -67,7 +66,10 @@ INTENT = ROOT / "INTENT.md"
# from layer.yaml's former `standard_version: "0.7"`, which recorded the same
# fact in a place the ruling says a declaration must not carry it. Bump it when
# the checker is re-validated against a newer accepted text.
VALIDATED_AGAINST = "net-kingdom/canon/standards/security-layer-model_v0.7.md"
VALIDATED_AGAINST = (
"net-kingdom/canon/standards/security-layer-model_v0.8.md "
"(accepted-1 sha256:3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b)"
)
# The scope every run ranges over, printed on every run (GH-DEC-2026-020 §4, A11).
# This is a single-repository run, not an estate run: it grades kings-guard, a §4
@ -77,18 +79,14 @@ SCOPE = (
"src/kings_guard, repository tree for credential files"
)
# A12 r2 detection. A key naming a version is a pin, except the sidecar's own
# A12 r3 detection. A key naming a standard/companion version is a pin; the sidecar's own
# schema_version. A value naming the standard or companion with a version, or any
# versioned file name, is a pin. In identity-bearing keys any version token is a
# pin. A bare "vN.N" elsewhere in a value is a citation: reported, not failed.
A12_EXEMPT_KEYS = {"schema_version"}
A12_IDENTITY_KEYS = {"standard", "companion", "framework"}
A12_PIN_VALUE = re.compile(
r"""(?ix)
(?:security[-_ ]?layer[-_ ]?model|security[-_ ]?companion)[^\s'"]*?[-_.]v?\d+(?:\.\d+)+
| [-_]v\d+(?:\.\d+)*\.(?:md|ya?ml|json)\b
"""
)
A12_IDENTITY_KEYS = {"standard", "companion"}
A12_VERSION_KEY = re.compile(r"(standard|companion).*version|version.*(standard|companion)", re.I)
A12_PIN_VALUE = re.compile(r"[_\-.]v\d+(\.\d+)*(\.md)?\b|@v?\d+\.\d+", re.I)
A12_VERSION_TOKEN = re.compile(r"\bv?\d+\.\d+(?:\.\d+)*\b")
A12_CITATION = re.compile(r"\bv\d+\.\d+\b")
@ -155,7 +153,7 @@ def a12_findings(node: object, where: str) -> tuple[list[str], list[str]]:
for k, v in value.items():
k_str = str(k)
sub = f"{path}.{k_str}" if path else k_str
if "version" in k_str.lower() and k_str not in A12_EXEMPT_KEYS:
if A12_VERSION_KEY.search(k_str) and k_str not in A12_EXEMPT_KEYS:
pins.append(f"{where}: key '{sub}' carries a version")
if k_str in A12_EXEMPT_KEYS:
continue
@ -165,11 +163,11 @@ def a12_findings(node: object, where: str) -> tuple[list[str], list[str]]:
for i, v in enumerate(value):
walk(v, f"{path}[{i}]", key)
return
if value is None or isinstance(value, bool):
if not isinstance(value, str):
return
text = str(value)
if A12_PIN_VALUE.search(text) or (
key in A12_IDENTITY_KEYS and A12_VERSION_TOKEN.search(text)
key and key.lower() in A12_IDENTITY_KEYS and A12_VERSION_TOKEN.search(text)
):
pins.append(f"{where}: '{path}' = {text!r} names a versioned standard")
elif A12_CITATION.search(text):
@ -354,7 +352,7 @@ def main() -> int:
+ a12_findings(decl, DECL.name)[1]
)
for citation in citations:
print(f"NOTE (A12 r2 reach unruled, reported not failed): {citation}")
print(f"NOTE (A12 r3 provenance, reported not failed): {citation}")
if forms_disagree(governing, decl["layer"]):
print("", file=sys.stderr)