Apply GH-DEC-2026-020: checker prints version and scope, A12 r2 by content.
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:
parent
b9151e20da
commit
c23918d6ec
4 changed files with 191 additions and 18 deletions
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue