kings-guard/scripts/check_layer_conformance.py

410 lines
17 KiB
Python
Raw Normal View History

Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
#!/usr/bin/env python3
"""Check kings-guard against the NetKingdom security layer model (§5, §11).
Read-only. kings-guard's whole position under the standard rests on one claim:
it holds no direct client for any Tooling-layer system, and the
capabilities that would need one sit at zero instead (§11 blocked-clean)
That claim has been asserted in prose since KG-DEC-2026-001. §11 (v0.7) requires
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
a machine-readable declaration because prose cannot distinguish a declaration
from a transcribed review. This script is what makes the claim checkable: it
fails if a Tooling client appears in src/ without a matching layer.yaml entry.
The failure it exists to catch is a *convenience* someone reaching for an
OpenBao or cluster client during an incident because the engine surface still
does not exist (§9.2). That is precisely the "small convenience" §6 warns about,
and it would arrive as a one-line import.
Declaration form (GH-DEC-2026-017, amendments A9, A11, A12): INTENT.md's
frontmatter `layer:` key governs; layer.yaml is a derived artifact that must be
marked derived, name INTENT.md, and agree with it. Layer comparison ASCII-folds
case against §3's closed four-token vocabulary, so `Staff` and `staff` agree and
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
`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
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.
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
that fail (GH-DEC-2026-020 §4). A run is sufficient; nothing durable is emitted.
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
Review dates are reported, never enforced: a date-triggered failure breaks the
build on a calendar day with no code change.
Exit 0 clean, 1 undeclared contact found or the two declaration forms disagree,
2 declaration malformed.
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
"""
from __future__ import annotations
import argparse
import ast
import re
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
import sys
from datetime import date
from pathlib import Path
import yaml
ROOT = Path(__file__).resolve().parents[1]
SRC = ROOT / "src" / "kings_guard"
DECL = ROOT / "layer.yaml"
INTENT = ROOT / "INTENT.md"
# The standard text this checker was built and validated against. This is the
# derived conformance record's version (GH-DEC-2026-017 §5 / A12), moved here
# 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"
# 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
# row, and nothing else.
SCOPE = (
"kings-guard only (§4 row, Staff): INTENT.md frontmatter, layer.yaml, "
"src/kings_guard, repository tree for credential files"
)
# A12 r2 detection. A key naming a version is a pin, except 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_VERSION_TOKEN = re.compile(r"\bv?\d+\.\d+(?:\.\d+)*\b")
A12_CITATION = re.compile(r"\bv\d+\.\d+\b")
# §3's closed layer vocabulary (A9): four tokens, compared ASCII case-insensitively.
LAYER_VOCABULARY = {"taxonomy", "tooling", "engine", "staff"}
EXPECTED_LAYER = "staff" # kings-guard's own §4 row, folded
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
# Import roots that would constitute a direct Tooling-layer client under §4.
# Matched against the top-level module of every import in src/.
TOOLING_IMPORTS = {
"hvac": "OpenBao / Vault client",
"bao": "OpenBao client",
"kubernetes": "cluster client",
"kubernetes_asyncio": "cluster client",
"psycopg": "direct database connection",
"psycopg2": "direct database connection",
"asyncpg": "direct database connection",
"sqlalchemy": "direct database connection",
"pymysql": "direct database connection",
"redis": "direct datastore connection",
"ldap3": "direct LDAP client (key-cape tooling)",
"python_ldap": "direct LDAP client (key-cape tooling)",
"docker": "container runtime client",
}
# §3.4 rule 1 — no standing credential held in the repository or its
# configuration. Filenames that would be a standing secret, and assignments
# of well-known secret env vars to string literals in src/.
CREDENTIAL_FILENAMES = {
".env",
".env.local",
".env.production",
"credentials.json",
"secrets.yaml",
"secrets.yml",
"id_rsa",
"id_ed25519",
"id_ecdsa",
}
CREDENTIAL_LITERAL = re.compile(
r"""(?x)
\b(?:VAULT_TOKEN|OPENBAO_TOKEN|BAO_TOKEN|AWS_SECRET_ACCESS_KEY|
PRIVATE_KEY|BEGIN\ (?:RSA\ )?PRIVATE\ KEY)
"""
)
SKIP_CREDENTIAL_SCAN_DIRS = {".git", ".venv", "__pycache__", ".pytest_cache", ".ruff_cache"}
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
def fold(value: object) -> str:
"""ASCII case-fold, per §3 as amended (A9): two spellings are one token."""
return str(value).encode("ascii", "replace").decode("ascii").lower()
def a12_findings(node: object, where: str) -> tuple[list[str], list[str]]:
"""Every key and value of a declaration form, walked (A12 r2).
Returns (pins, citations). Pins fail the run; citations are reported.
"""
pins: list[str] = []
citations: list[str] = []
def walk(value: object, path: str, key: str | None) -> None:
if isinstance(value, dict):
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:
pins.append(f"{where}: key '{sub}' carries a version")
if k_str in A12_EXEMPT_KEYS:
continue
walk(v, sub, k_str)
return
if isinstance(value, list):
for i, v in enumerate(value):
walk(v, f"{path}[{i}]", key)
return
if value is None or isinstance(value, bool):
return
text = str(value)
if A12_PIN_VALUE.search(text) or (
key 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):
match = A12_CITATION.search(text).group(0)
citations.append(f"{where}: '{path}' cites {match} in prose")
walk(node, "", None)
return pins, citations
def _refuse_pins(pins: list[str]) -> None:
if pins:
_malformed(
"a layer declaration MUST NOT carry a standard or companion version "
"in any key or value (§11 as amended by A12 r2, GH-DEC-2026-020 §1§2):\n "
+ "\n ".join(pins)
)
def _malformed(message: str) -> None:
print(f"FAIL: {message}", file=sys.stderr)
raise SystemExit(2)
def load_intent_frontmatter() -> dict:
"""INTENT.md's frontmatter, parsed; the governing declaration form (§11)."""
if not INTENT.exists():
_malformed(f"no {INTENT.name} — §11's governing declaration form")
lines = INTENT.read_text().splitlines()
if not lines or lines[0].strip() != "---":
_malformed(f"{INTENT.name} has no frontmatter to carry the declaration (§11)")
try:
end = lines[1:].index("---") + 1
except ValueError:
_malformed(f"{INTENT.name} frontmatter is not terminated")
try:
front = yaml.safe_load("\n".join(lines[1:end])) or {}
except yaml.YAMLError as exc:
_malformed(f"{INTENT.name} frontmatter is not parseable: {exc}")
if not isinstance(front, dict):
_malformed(f"{INTENT.name} frontmatter is not a mapping")
return front
def load_governing_layer() -> str:
"""The declaration: INTENT.md frontmatter `layer:` (§11, GH-DEC-2026-017 §1)."""
front = load_intent_frontmatter()
if "layer" not in front:
_malformed(f"{INTENT.name} frontmatter has no 'layer' key — §11's declaration")
_refuse_pins(a12_findings(front, f"{INTENT.name} frontmatter")[0])
layer = front["layer"]
if fold(layer) not in LAYER_VOCABULARY:
_malformed(
f"{INTENT.name} declares layer {layer!r}, outside §3's closed vocabulary "
f"{sorted(LAYER_VOCABULARY)} (case-insensitive)"
)
if fold(layer) != EXPECTED_LAYER:
_malformed(f"{INTENT.name} declares layer {layer!r}, expected Staff (§4 row)")
return str(layer)
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
def load_declaration() -> dict:
"""The derived form, layer.yaml (§11 derived-artifact rule)."""
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
if not DECL.exists():
_malformed(f"no declaration at {DECL.relative_to(ROOT)} (§11)")
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
try:
data = yaml.safe_load(DECL.read_text())
except yaml.YAMLError as exc:
print(f"FAIL: {DECL.name} is not parseable: {exc}", file=sys.stderr)
raise SystemExit(2) from exc
for key in ("layer", "repository", "tooling_contacts", "derived", "derived_from"):
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
if key not in data:
_malformed(f"{DECL.name} missing required key '{key}' (§11)")
if data["derived"] is not True:
_malformed(f"{DECL.name} must be marked 'derived: true' (§11, GH-DEC-2026-017 §1)")
if data["derived_from"] != "INTENT.md":
_malformed(
f"{DECL.name} derives from {data['derived_from']!r}; §11 names INTENT.md "
"as the governing declaration"
)
_refuse_pins(a12_findings(data, DECL.name)[0])
if fold(data["layer"]) not in LAYER_VOCABULARY:
_malformed(
f"{DECL.name} declares layer {data['layer']!r}, outside §3's closed "
f"vocabulary {sorted(LAYER_VOCABULARY)} (case-insensitive)"
)
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
return data
def forms_disagree(governing: object, derived: object) -> bool:
"""A11: the derived form must agree with INTENT.md, after the A9 case fold."""
return fold(governing) != fold(derived)
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
def imported_modules(path: Path) -> set[str]:
"""Top-level module name of every import in one file."""
try:
tree = ast.parse(path.read_text())
except SyntaxError:
return set()
found: set[str] = set()
for node in ast.walk(tree):
if isinstance(node, ast.Import):
found.update(alias.name.split(".")[0] for alias in node.names)
elif isinstance(node, ast.ImportFrom):
if node.level == 0 and node.module:
found.add(node.module.split(".")[0])
return found
def scan() -> list[tuple[Path, str, str]]:
hits: list[tuple[Path, str, str]] = []
for path in sorted(SRC.rglob("*.py")):
for module in sorted(imported_modules(path)):
if module in TOOLING_IMPORTS:
hits.append((path, module, TOOLING_IMPORTS[module]))
return hits
def scan_standing_credentials() -> list[tuple[Path, str]]:
"""§3.4 rule 1: no standing credential in the repository or its config."""
hits: list[tuple[Path, str]] = []
for path in ROOT.rglob("*"):
if not path.is_file():
continue
if any(part in SKIP_CREDENTIAL_SCAN_DIRS for part in path.parts):
continue
if path.name in CREDENTIAL_FILENAMES:
hits.append((path, f"credential-shaped file {path.name}"))
continue
if path.suffix in {".pem", ".key"} and "test" not in path.parts:
hits.append((path, f"key material file {path.name}"))
if SRC.is_dir():
for path in sorted(SRC.rglob("*.py")):
text = path.read_text(encoding="utf-8")
if CREDENTIAL_LITERAL.search(text):
hits.append((path, "standing-credential literal or private-key block"))
return hits
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--report", action="store_true", help="print the declaration summary")
args = parser.parse_args()
# Every run, pass or fail, states what it checks against and over what
# (GH-DEC-2026-020 §4). Printed before anything can exit.
print(f"checking against: {VALIDATED_AGAINST}")
print(f"scope: {SCOPE}")
governing = load_governing_layer()
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
decl = load_declaration()
declared = {c.get("id") for c in decl.get("tooling_contacts") or []}
hits = scan()
credential_hits = scan_standing_credentials()
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
undeclared = [h for h in hits if h[1] not in declared]
rules = decl.get("agent_principal_rules") or {}
checks = decl.get("agent_principal_rule_checks") or {}
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
if args.report:
print(f"kings-guard — layer: {governing} (declared in INTENT.md; §11 governing form)")
print(f" layer.yaml: derived from {decl['derived_from']}, layer: {decl['layer']}")
print(f" checker validated against: {VALIDATED_AGAINST}")
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
print(f" tooling contacts declared: {len(declared)}")
print(f" unowned capabilities (§11 blocked-clean): "
f"{len(decl.get('unowned_capabilities') or [])}")
today = date.today()
for cap in decl.get("unowned_capabilities") or []:
review = cap.get("review")
stale = ""
if review and date.fromisoformat(str(review)) < today:
stale = " [REVIEW OVERDUE]"
print(f" - {cap['id']}: {cap.get('owner_status', '?')}{stale}")
print(" agent-principal rule checks (§3.4):")
for name, meta in checks.items():
form = meta.get("form", "unspecified") if isinstance(meta, dict) else "unspecified"
print(f" - {name}: {form} (claimed={rules.get(name)})")
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
citations = (
a12_findings(load_intent_frontmatter(), f"{INTENT.name} frontmatter")[1]
+ a12_findings(decl, DECL.name)[1]
)
for citation in citations:
print(f"NOTE (A12 r2 reach unruled, reported not failed): {citation}")
if forms_disagree(governing, decl["layer"]):
print("", file=sys.stderr)
print("FAIL: the two declaration forms disagree (§11, A11)", file=sys.stderr)
print(f" INTENT.md (governs): layer: {governing}", file=sys.stderr)
print(f" layer.yaml (derived): layer: {decl['layer']}", file=sys.stderr)
print(" Case is already folded, so this is a real layer disagreement.", file=sys.stderr)
print(" It is a finding in its own right; precedence does not erase it.", file=sys.stderr)
return 1
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
if undeclared:
print("", file=sys.stderr)
print("FAIL: undeclared Tooling-layer client (§11 undeclared violation)", file=sys.stderr)
for path, module, what in undeclared:
rel = path.relative_to(ROOT)
print(f" {rel}: imports '{module}'{what}", file=sys.stderr)
print("", file=sys.stderr)
print(" A Staff repository may not hold a direct Tooling client (§5).", file=sys.stderr)
print(" Route it through the owning engine, or if none exists, raise an", file=sys.stderr)
print(" engine gap — do not declare this to make the check pass.", file=sys.stderr)
return 1
if credential_hits:
print("", file=sys.stderr)
print("FAIL: standing credential material (§3.4 rule 1)", file=sys.stderr)
for path, what in credential_hits:
try:
rel = path.relative_to(ROOT)
except ValueError:
rel = path
print(f" {rel}: {what}", file=sys.stderr)
print("", file=sys.stderr)
print(" Authority is per task, time-bounded, and attributable to the", file=sys.stderr)
print(" principal acted for. Do not hold a standing secret here.", file=sys.stderr)
return 1
if rules.get("no_standing_credential") is not True:
print("FAIL: layer.yaml does not claim no_standing_credential (§3.4 rule 1)", file=sys.stderr)
return 2
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
if not args.report:
print(
f"OK: no direct Tooling client in {SRC.relative_to(ROOT)}; "
"no standing credential (§5, §11, §3.4 rule 1); "
"declaration forms agree; no standard or companion version in "
f"either form; validated against {VALIDATED_AGAINST}; scope: {SCOPE}"
)
Declare layer machine-readably (§11); adopt v0.6 corrections The standard moved v0.4 -> v0.6. All four findings from our v0.4 review were adopted in v0.5, and v0.6 went further on two of them. §11 now requires a machine-readable declaration — prose cannot distinguish a declaration from a transcribed review. We had none. Added layer.yaml (form adapted from ops-warden's reference implementation), scripts/check_layer_conformance.py, and tests/test_layer_conformance.py. The check makes our central claim mechanical rather than asserted: no direct Tooling client in src/. The test exercises the negative case on a synthetic tree, so it fails if the checker goes blind. pyyaml is added as a DEV dependency only — `dependencies = []` is load-bearing for the §5 claim and stays empty. Adopted from v0.6: - containment is no longer ours (§9.2). Actuation is an Engine concept, unowned and held at zero; kings-guard proposes containment and never performs it. The register row is now a dependency, not our gap. - observation is scoped to Staff-reachable sources, with identity and secret observation pending — our finding 1, adopted near-verbatim. - access-engine DECLINED the authentication-evidence gap; owner is now the identity layer plus audit-core, reproposed and unassented. - §11 blocked-clean recorded, with the rule that it must not rank below conforming — our finding 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEtvmYUBP2fDtirJGWn5MW Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014379@bnt-lap001 Assistant-Session: 4af9e20f-1768-4afc-951b-b507784e382b
2026-08-29 10:20:39 +02:00
return 0
if __name__ == "__main__":
raise SystemExit(main())