Apply GH-DEC-2026-020: checker prints version and scope, A12 r2 by content.
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 2s

The layer conformance checker now prints VALIDATED_AGAINST and SCOPE on every
run, including the PASS line (kings-guard pattern), and enforces A12 r2 over
every key and value of INTENT.md frontmatter and layer.yaml: a versioned
standard: path and a companion_version are caught, schema_version and comments
are not reached, pep-stance.yaml is outside the run. Tests guard both returns.
The playbook carries the adopter change set and confirms the section 5
citation is canonical. WARDEN-WP-0034's open 4220413a note is closed.

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:38:17 +02:00
parent b9151e20da
commit c23918d6ec
4 changed files with 191 additions and 18 deletions

View file

@ -13,8 +13,19 @@ comparing (`GH-DEC-2026-017` §2, amendment A9): two spellings of a token do not
describe two boundaries, and a check that reports findings about capital letters
buries the one real disagreement it exists to find.
Neither form carries a `standard_version`, and their absence is enforced here
and by tests (`GH-DEC-2026-017` §5, amendment A12).
Neither form carries a version of the standard or of its companion, in any key
or value (`GH-DEC-2026-017` §5, amendment A12 as refined by A12 r2 /
`GH-DEC-2026-020` §1-§2). The rule reaches content, not a key name: a
`standard_version` key, a `companion_version` key, and a version-bearing path
such as `standard: .../security-layer-model_v0.7.md` are the same pin. Comments
and a file's own `schema_version` are not reached. Stance, claims and
evidence-classification maps (`pep-stance.yaml`) are NOT declarations and this
check does not read them (`GH-DEC-2026-020` §3).
The version belongs to the run (`GH-DEC-2026-020` §4): every run prints
VALIDATED_AGAINST and SCOPE below, including the PASS line, following
kings-guard's pattern. A retained copy of this output is a derived artifact
whose version is owed by whoever retains it.
Makes §11's second mechanical check real:
@ -47,6 +58,61 @@ DECL = ROOT / "layer.yaml"
VALID_SHAPES = {"5.1", "5.2", "5.3"}
# What every run checks against, printed on every run (GH-DEC-2026-020 §4, A12 r2).
# The accepted text is v0.7 at net-kingdom@66dc491; the amendments that already
# govern through their decision records are named with it.
VALIDATED_AGAINST = (
"net-kingdom/canon/standards/security-layer-model_v0.7.md (net-kingdom@66dc491) "
"as amended by GH-DEC-2026-017 and GH-DEC-2026-020 (A9-A13, A12 r2; gate-house@d8c82a8)"
)
# What every run ranges over. pep-stance.yaml is deliberately outside it.
SCOPE = "INTENT.md frontmatter, layer.yaml, src/warden/**/*.py"
# A12 r2: a version of the standard or companion in any key or value of the
# declaration. Keys: anything naming a standard/companion version. Values: a
# versioned file name or path (`_v0.7`, `-v0.8.md`) or a bare version string on a
# version-named key. `schema_version` is the file's own schema, not reached.
VERSION_KEY = re.compile(r"(standard|companion).*version|version.*(standard|companion)", re.I)
VERSION_IN_VALUE = re.compile(r"[_\-.]v\d+(\.\d+)*(\.md)?\b|@v?\d+\.\d+", re.I)
NOT_REACHED_KEYS = {"schema_version"}
def find_version_pins(node, where: str = "") -> list[str]:
"""Every place in a parsed declaration that carries a standard/companion version.
Walks every key and value (comments are gone after parsing, which is the
A12 r2 exclusion). Returns human-readable locations; empty means clean.
"""
pins: list[str] = []
if isinstance(node, dict):
for k, v in node.items():
here = f"{where}.{k}" if where else str(k)
if str(k) in NOT_REACHED_KEYS:
continue
if VERSION_KEY.search(str(k)):
pins.append(f"{here} (key names a standard/companion version)")
continue
pins.extend(find_version_pins(v, here))
elif isinstance(node, list):
for i, v in enumerate(node):
pins.extend(find_version_pins(v, f"{where}[{i}]"))
elif isinstance(node, str) and VERSION_IN_VALUE.search(node):
pins.append(f"{where} = {node!r} (value carries a version)")
return pins
def _reject_version_pins(label: str, node) -> None:
pins = find_version_pins(node)
if pins:
print(
f"MALFORMED: {label} carries a standard/companion version — a layer "
"declaration MUST NOT, in any key or value (§11 as amended by A12 r2, "
"GH-DEC-2026-020 §1-§2):"
)
for p in pins:
print(f" {p}")
raise SystemExit(2)
# §3's vocabulary, closed, four tokens (GH-DEC-2026-017 §3, amendment A9). The
# canonical spellings are §4's catalog-column forms; comparison is ASCII
# case-insensitive, so the fold is what is stored and `Taxonomy` is in the set —
@ -80,12 +146,7 @@ def load_governing_layer() -> str:
if "layer" not in front:
print("MALFORMED: INTENT.md frontmatter has no 'layer' key — §11's declaration")
raise SystemExit(2)
if "standard_version" in front:
print(
"MALFORMED: INTENT.md frontmatter carries 'standard_version' — a layer "
"declaration MUST NOT carry a standard version (§11 as amended by A12)"
)
raise SystemExit(2)
_reject_version_pins("INTENT.md frontmatter", front)
layer = front["layer"]
if _fold(layer) not in LAYER_VOCABULARY:
print(
@ -139,12 +200,7 @@ def load_declaration() -> dict:
)
raise SystemExit(2)
# A12: the version has no home in a declaration, governing or derived.
if "standard_version" in decl:
print(
"MALFORMED: layer.yaml carries 'standard_version' — a layer declaration "
"MUST NOT carry a standard version (§11 as amended by A12)"
)
raise SystemExit(2)
_reject_version_pins("layer.yaml", decl)
if _fold(decl["layer"]) not in LAYER_VOCABULARY:
print(
f"MALFORMED: layer.yaml declares layer {decl['layer']!r}, outside §3's "
@ -197,6 +253,10 @@ def main() -> int:
ap.add_argument("--report", action="store_true", help="also print the declaration and gap review dates")
args = ap.parse_args()
# Printed before anything can fail, so even a MALFORMED run states what it
# checked against and over what (GH-DEC-2026-020 §4).
print(f"validated against: {VALIDATED_AGAINST}")
print(f"scope: {SCOPE}")
governing = load_governing_layer()
decl = load_declaration()
declared = {c["module"].split("/")[-1] for c in decl["tooling_contacts"]}
@ -258,9 +318,15 @@ def main() -> int:
print(f" {m}")
if ok and not args.report:
print(f"PASS — {len(found)} module(s) with Tooling contact, all declared.")
print(
f"PASS — {len(found)} module(s) with Tooling contact, all declared; "
f"validated against {VALIDATED_AGAINST}"
)
elif ok:
print("\nPASS — every direct Tooling contact maps to a declared shape.")
print(
"\nPASS — every direct Tooling contact maps to a declared shape; "
f"validated against {VALIDATED_AGAINST}"
)
return 0 if ok else 1

View file

@ -32,6 +32,17 @@ def _intent_frontmatter() -> dict:
return yaml.safe_load("\n".join(lines[1:end]))
def _checker():
import importlib.util
spec = importlib.util.spec_from_file_location(
"check_layer_conformance", ROOT / "scripts" / "check_layer_conformance.py"
)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def _fold(value: str) -> str:
return str(value).strip().encode("ascii", "ignore").decode().lower()
@ -81,6 +92,51 @@ class TestDeclaration:
assert "standard_version" not in _decl()
assert "standard_version" not in _intent_frontmatter()
def test_no_version_anywhere_in_either_declaration(self):
"""A12 r2 / GH-DEC-2026-020 §1-§2: content, not a key name.
A versioned `standard:` path or a `companion_version` is the same pin as
`standard_version`, so the guard walks every key and value of both forms.
"""
checker = _checker()
assert checker.find_version_pins(_intent_frontmatter()) == []
assert checker.find_version_pins(_decl()) == []
assert not str(_intent_frontmatter()["standard"]).endswith(".md")
def test_checker_catches_a_versioned_standard_path(self):
checker = _checker()
pins = checker.find_version_pins(
{"layer": "Staff", "standard": "net-kingdom/canon/standards/security-layer-model_v0.7.md"}
)
assert pins and pins[0].startswith("standard")
def test_checker_catches_a_companion_version(self):
checker = _checker()
assert checker.find_version_pins({"layer": "Staff", "companion_version": "0.2"})
assert checker.find_version_pins({"nested": {"standard_version": "0.7"}})
def test_schema_version_is_not_reached(self):
assert _checker().find_version_pins({"schema_version": "0.2", "layer": "Staff"}) == []
def test_stance_map_is_outside_the_run(self):
"""GH-DEC-2026-020 §3: a stance map keeps its version; the run must not read it."""
stance = yaml.safe_load((ROOT / "pep-stance.yaml").read_text())
assert "standard_version" in stance, "pep-stance.yaml keeps its clause-scoped version"
assert "pep-stance" not in _checker().SCOPE
def test_every_run_states_version_and_scope(self):
"""GH-DEC-2026-020 §4: the version belongs to the run, printed every time."""
checker = _checker()
out = subprocess.run(
[sys.executable, str(ROOT / "scripts" / "check_layer_conformance.py")],
capture_output=True,
text=True,
).stdout
assert f"validated against: {checker.VALIDATED_AGAINST}" in out
assert f"scope: {checker.SCOPE}" in out
pass_line = next(ln for ln in out.splitlines() if ln.startswith("PASS"))
assert checker.VALIDATED_AGAINST in pass_line
def test_every_tooling_contact_maps_to_a_declared_shape(self):
"""§11 mechanical check — the guard against a new undeclared client."""
result = subprocess.run(

View file

@ -51,8 +51,10 @@ anyone else's files.
property that does not change when the standard is revised, and a version in
the declaration makes every revision read as though it invalidated every
declaration. Keeping it "for information" was declined explicitly — a field
that is present will be branched on. Version-scoped state belongs in the
derived conformance record. If your checker lists `standard_version` as a
that is present will be branched on. Version-scoped state belongs to the
conformance *run* (see the 2026-09-21 `GH-DEC-2026-020` section below; the
"derived conformance record" this line used to name was a defect in §5 and
nobody is required to emit one). If your checker lists `standard_version` as a
required key, or prints it in a report line, it will now **reject a conforming
declaration** — fix the checker in the same commit.
2. **Add `derived: true` and `derived_from: INTENT.md`.** The sidecar is a derived
@ -82,6 +84,49 @@ ops-warden's applied instance of this change set is commit-local: `INTENT.md`,
`layer.yaml`, `scripts/check_layer_conformance.py`, `tests/test_layer_conformance.py`.
Read those four together rather than the sidecar alone.
## Reach and run-version change set — 2026-09-21 (`GH-DEC-2026-020`, A12 r2)
**If you copied ops-warden's checker before this change, it enforces A12 by key
name only, and prints no version.** Both are now defects. `GH-DEC-2026-020`
refines A12 as A12 r2; verify it in `gate-house` `decisions/decisions.md` and
`docs/amendments/v0.8-section-11-declaration-amendments.md` (§ "A12 r2"), not
from this page.
1. **A version anywhere in the declaration counts.** The declaration is every key
and value of your `INTENT.md` frontmatter and of your derived sidecar. No key
or value carries a version of the standard **or of its companion**, including
a version-bearing path: `standard: .../security-layer-model_v0.7.md` becomes
`standard: .../security-layer-model` (`GH-DEC-2026-020` §1). A de-versioned
path was a required change, not a voluntary one.
2. **`companion_version` counts** and comes out of the declaration (§2).
3. **Not reached:** comments, and a file's own `schema_version`. Keeping or
removing them is equally fine; do not edit them just to tidy.
4. **Not a declaration, not checked:** stance maps (`pep-stance.yaml`), claims
maps, evidence classifications. Their version is what makes them re-readable
when clause text changes; keep it. Your checker **MUST NOT** apply A12 to
them (§3).
5. **The version belongs to the run.** A re-runnable checker is sufficient —
not "for now" — if **every** run prints the standard version or commit it
checks against and the scope it ranged over, including the PASS line (§4).
No repository must emit a durable conformance record; whoever retains a run's
output owes that copy's version. The pattern is kings-guard's: a
`VALIDATED_AGAINST` constant in the checker, printed on every run.
6. **Widen your checker from key name to content.** ops-warden's
`scripts/check_layer_conformance.py` now carries `VALIDATED_AGAINST`, `SCOPE`
and `find_version_pins()`, which walks every parsed key and value, skips
`schema_version`, and flags any key naming a standard/companion version and
any value carrying a versioned file name or path. It prints version and scope
before loading anything, so even a MALFORMED run states them. Copy that, set
`VALIDATED_AGAINST` to what *your* run checks against, and add tests that fail
if a versioned `standard:` path or a `companion_version` comes back
(`tests/test_layer_conformance.py` has the reference set). Change declaration,
checker and tests in the same commit, and re-spell no layer value.
**Citation.** Cite the ruling by the decision's body section: `GH-DEC-2026-017`
§5, statute A12 (now A12 r2). This page's "§5" is canonical
(`GH-DEC-2026-020`); the decision's `rationale:` part numbers are a summary and
are not cited.
## Ownership boundary
`gate-house` owns what the model requires. Each repository owns the truth of its

View file

@ -292,6 +292,12 @@ says version-scoped state belongs in the derived conformance record, which
checker that emits nothing durable, not an emitted record. Whether §11 expects an
emitted artifact or a re-runnable check discharges it is asked of gate-house in
message `4220413a` and unanswered. Nothing applied above depends on the answer.
**Closed 2026-09-21 by `GH-DEC-2026-020` §4 (gate-house@104f3fc):** §5 was wrong
that the record exists; a re-runnable checker is sufficient if every run prints
the version it checks against and its scope. Applied: the checker now prints
`VALIDATED_AGAINST` and `SCOPE` on every run and enforces A12 r2 by content, not
key name (versioned `standard:` path, `companion_version`); `pep-stance.yaml`
untouched per §3; the playbook carries the adopter change set.
**Ruled the same day, and still `wait` — deliberately.** `GH-DEC-2026-017`
(message `3715e247`) landed hours later: `INTENT.md` governs, the sidecar is a