Bind checker to accepted v0.8 and preserve provenance distinctions
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade Assistant-Process: 8340@bnt-lap001
This commit is contained in:
parent
363e8160a4
commit
79ea443d9c
4 changed files with 98 additions and 35 deletions
31
docs/conformance/2026-10-11-layer-v08-migration.md
Normal file
31
docs/conformance/2026-10-11-layer-v08-migration.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
type: conformance-record
|
||||
derived: true
|
||||
derived_from: net-kingdom/canon/standards/security-layer-model_v0.8.md
|
||||
derived_source_sha256: "3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b"
|
||||
updated: "2026-10-11"
|
||||
---
|
||||
|
||||
# maturity-engine accepted v0.8 checker migration
|
||||
|
||||
This owner applies GH-WP-0004-T11's post-flip migration to the confirmed
|
||||
accepted NetKingdom v0.8 cut, immutable accepted-1 artifact SHA256
|
||||
3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b.
|
||||
The checker names that artifact and its local scope in every run. INTENT
|
||||
frontmatter remains authoritative and the sidecar remains derived; a
|
||||
contradiction is a finding, never hidden by choosing one form. No declaration
|
||||
acquires a standard version.
|
||||
|
||||
The pin detector follows OpsWarden's A12 r3 reference semantics: standard and
|
||||
companion identity values (including nested lists), version-bearing paths and
|
||||
standard/companion version keys are pins; unrelated intent/schema/spec versions
|
||||
and bare prose provenance are not. Existing local Tooling/contact and capability
|
||||
detectors remain in place. Historical version strings in negative fixtures are
|
||||
retained. This source migration grants no native capability or runtime authority.
|
||||
|
||||
Validation includes the existing local declaration/contact suite and the same
|
||||
12-case pin/provenance corpus across all four assigned owners, with exact
|
||||
accepted-artifact and scope assertions. The local test counts and staged source
|
||||
digests are retained in the coordinating Custodian evidence receipt. Standalone
|
||||
checker runs continue to inspect only this repository; no estate-wide compliance
|
||||
claim or novel declaration is produced.
|
||||
|
|
@ -37,8 +37,8 @@ import yaml
|
|||
# carry this (A12); the run does. Bump it when re-validated against a newer
|
||||
# accepted text.
|
||||
VALIDATED_AGAINST = (
|
||||
"net-kingdom/canon/standards/security-layer-model_v0.7.md"
|
||||
" (+ GH-DEC-2026-017, GH-DEC-2026-020 / A12 r2)"
|
||||
"net-kingdom/canon/standards/security-layer-model_v0.8.md "
|
||||
"(accepted-1 sha256:3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b)"
|
||||
)
|
||||
|
||||
# §3 as amended (A9): closed, four tokens, compared after an ASCII case fold.
|
||||
|
|
@ -47,7 +47,7 @@ LAYER_VOCABULARY = {"taxonomy", "tooling", "engine", "staff"}
|
|||
|
||||
def _fold(value: object) -> str:
|
||||
"""ASCII case-fold: two spellings of a token are one token."""
|
||||
return str(value).strip().encode("ascii", "ignore").decode().lower()
|
||||
return str(value).strip().translate(str.maketrans("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"))
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
|
@ -63,40 +63,30 @@ SCOPE = "INTENT.md frontmatter, layer.yaml, imports under src/maturity_engine"
|
|||
# `standard_version`. `schema_version` is the file format's own version, not a
|
||||
# standard version, and is not reached (GH-DEC-2026-020 §1).
|
||||
EXEMPT_VERSION_KEYS = {"schema_version"}
|
||||
# A version-bearing path or file name, e.g. `security-layer-model_v0.7.md`,
|
||||
# `.../v0.2/companion.md`. Matched only against whitespace-free values, so prose
|
||||
# notes citing a rule's history are not mistaken for a pin.
|
||||
VERSIONED_PATH = re.compile(r"(?i)(?:^|[_\-/.])v\d+(?:\.\d+)*(?:$|[_\-/.])")
|
||||
# Keys that name a standard or companion: any version-like token in their value counts.
|
||||
STANDARD_KEYS = {"standard", "companion", "framework"}
|
||||
BARE_VERSION = re.compile(r"\d+\.\d+")
|
||||
VERSION_KEY = re.compile(r"(standard|companion).*version|version.*(standard|companion)", re.I)
|
||||
VERSIONED_PATH = re.compile(r"[_\-.]v\d+(\.\d+)*(\.md)?\b|@v?\d+\.\d+", re.I)
|
||||
STANDARD_KEYS = {"standard", "companion"}
|
||||
BARE_VERSION = re.compile(r"\bv?\d+\.\d+", re.I)
|
||||
|
||||
|
||||
def version_findings(data: object, where: str) -> list[str]:
|
||||
"""Every place a standard or companion version appears in a declaration."""
|
||||
def version_findings(data: object, where: str, identity: bool = False) -> list[str]:
|
||||
"""A12 r3 pins; bare prose provenance and unrelated versions are not pins."""
|
||||
found: list[str] = []
|
||||
|
||||
def walk(node: object, path: str, key: str | None) -> None:
|
||||
if isinstance(node, dict):
|
||||
for k, v in node.items():
|
||||
ks = str(k)
|
||||
if ks in EXEMPT_VERSION_KEYS:
|
||||
continue
|
||||
if "version" in ks.lower():
|
||||
found.append(f"{where}: key '{path}{ks}' carries a version")
|
||||
walk(v, f"{path}{ks}.", ks)
|
||||
elif isinstance(node, list):
|
||||
for i, v in enumerate(node):
|
||||
walk(v, f"{path}{i}.", key)
|
||||
elif isinstance(node, str):
|
||||
value = node.strip()
|
||||
label = path.rstrip(".")
|
||||
if key and key.lower() in STANDARD_KEYS and BARE_VERSION.search(value):
|
||||
found.append(f"{where}: '{label}' value {value!r} carries a version")
|
||||
elif value and not any(c.isspace() for c in value) and VERSIONED_PATH.search(value):
|
||||
found.append(f"{where}: '{label}' value {value!r} is a version-bearing path")
|
||||
|
||||
walk(data, "", None)
|
||||
if isinstance(data, dict):
|
||||
for key, value in data.items():
|
||||
name = str(key)
|
||||
here = f"{where}.{name}" if where else name
|
||||
if name in EXEMPT_VERSION_KEYS:
|
||||
continue
|
||||
if VERSION_KEY.search(name):
|
||||
found.append(f"{here} names a standard/companion version")
|
||||
continue
|
||||
found.extend(version_findings(value, here, name.lower() in STANDARD_KEYS))
|
||||
elif isinstance(data, list):
|
||||
for index, item in enumerate(data):
|
||||
found.extend(version_findings(item, f"{where}[{index}]", identity))
|
||||
elif isinstance(data, str) and (VERSIONED_PATH.search(data) or identity and BARE_VERSION.search(data)):
|
||||
found.append(f"{where} = {data!r} carries a standard/companion version")
|
||||
return found
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ def test_no_version_anywhere_in_either_declaration():
|
|||
{"companion": "net-kingdom/v0.2/SECURITY-COMPANION.md"},
|
||||
{"companion_version": "0.2"},
|
||||
{"standard_version": "0.7"},
|
||||
{"framework": "netkingdom-security-layer-model 0.8"},
|
||||
{"standard": ["netkingdom-security-layer-model 0.8"]},
|
||||
],
|
||||
)
|
||||
def test_checker_catches_a_version_beyond_the_key_name(declaration):
|
||||
|
|
|
|||
42
tests/test_layer_v08_convergence.py
Normal file
42
tests/test_layer_v08_convergence.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
"""Accepted A12 r3 semantics, retaining local contact scanners and scope."""
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SCRIPT = ROOT / "scripts/check_layer_conformance.py"
|
||||
|
||||
def checker():
|
||||
spec = importlib.util.spec_from_file_location("v08_checker", SCRIPT)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
@pytest.mark.parametrize("value,pinned", [
|
||||
({"intent_version": "0.3"}, False),
|
||||
({"spec_version": "0.7"}, False),
|
||||
({"note": "per v0.6 section 13"}, False),
|
||||
({"note": "revised 0.7 wording"}, False),
|
||||
({"schema_version": "0.1"}, False),
|
||||
({"standard": "security-layer-model 0.8"}, True),
|
||||
({"STANDARD": ["security-layer-model v0.8"]}, True),
|
||||
({"companion": [["SECURITY-COMPANION v0.3"]]}, True),
|
||||
({"nested": {"standard_version": "0.8"}}, True),
|
||||
({"nested": {"companion_version": "0.3"}}, True),
|
||||
({"references": ["security-layer-model@0.8"]}, True),
|
||||
({"references": ["security-layer-model_v0.7.md"]}, True),
|
||||
])
|
||||
def test_reference_pin_provenance_semantics(value, pinned):
|
||||
module = checker()
|
||||
assert bool(module.version_findings(value, "test")) is pinned
|
||||
|
||||
def test_run_names_exact_accepted_standard_and_scope():
|
||||
module = checker()
|
||||
assert "security-layer-model_v0.8.md" in module.VALIDATED_AGAINST
|
||||
assert "3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b" in module.VALIDATED_AGAINST
|
||||
assert "INTENT.md" in module.SCOPE
|
||||
|
||||
def test_ascii_fold_never_discards_non_ascii_characters():
|
||||
module = checker()
|
||||
assert module._fold("Enginée") not in module.LAYER_VOCABULARY
|
||||
assert module._fold("ENGINE") == "engine"
|
||||
Loading…
Add table
Add a link
Reference in a new issue