Apply GH-DEC-2026-017: INTENT.md governs, the sidecar is derived, no version
Verified against gate-house's own committed files before editing, not the inbox message: GH-DEC-2026-017 in decisions/decisions.md at gate-house@def0af2, amendments A9-A13 in docs/amendments/v0.8-section-11-declaration-amendments.md, and sections 3, 4 and 11 of net-kingdom's security-layer-model_v0.8.md. The ruling and docs/layer-declaration-precedence.md's secondary account agreed. INTENT.md's frontmatter is the declaration; layer.yaml is a derived artifact, now marked derived: true / derived_from: INTENT.md, and it does not govern. standard_version is removed from BOTH forms. The ruling's general form is that a layer declaration must not carry a standard version, and INTENT.md is the declaration, so removing it from the sidecar alone would have left the field in the only file that actually declares. INTENT.md's version-pinned `standard:` path is de-versioned for the same reason: a pinned path reads as a validity condition. The version ops-warden assented at stays with the assent, ADR-0010. NO LAYER VALUE IS CHANGED. INTENT.md still says Staff and layer.yaml still says staff. Section 3's vocabulary is closed, four tokens, and case-insensitive: the two forms were never in disagreement about a layer, and the ruling asked nobody to re-spell anything. The comment marking the divergence is rewritten from "unruled, do not touch" to "ruled, folding case is the checker's job". check_layer_conformance.py would have rejected the conforming declaration this ruling produces -- it listed standard_version as a required key. It now reads INTENT.md as the governing form, ASCII-folds before comparing, validates both values against the closed four-token vocabulary (Taxonomy included; omitting it is the defect A9 records against the estate's other validator), requires the derived marking, rejects a returning standard_version in either file, and reports a post-fold disagreement between the forms as a finding rather than resolving it away by precedence. The test asserts the fold, not equality. An equality assertion here would be this repository quietly performing the re-spelling the ruling declined to order; the fold still fails on a real layer divergence. pep-stance.yaml is untouched. A stance map is not a layer declaration, and the sidecar schema beyond the derived marking and the version is explicitly not ruled. layer.yaml is the form seven repositories copied, so the adopter change set is written out in wiki/playbooks/netkingdom-layer-declaration.md -- including the trap that an adopter which also copied the checker turns a conforming declaration into MALFORMED exit 2 by removing the field alone. No other repository is edited here. Still open: where the removed version lives. A12 says the derived conformance record "already MUST" carry it; ops-warden has a re-runnable checker that emits nothing durable. Asked of gate-house in message 4220413a, unanswered, and left open rather than answered by choosing. Nothing above depends on it. Carries WARDEN-WP-0034-T06 to done. 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
04b3a28aaa
commit
a70f559d40
8 changed files with 376 additions and 73 deletions
|
|
@ -1,7 +1,22 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Check ops-warden against the NetKingdom security layer model (§5, §11).
|
||||
|
||||
Read-only. Makes §11's second mechanical check real:
|
||||
Read-only. Two declaration forms are read, and the precedence between them is
|
||||
`GH-DEC-2026-017` §1 (amendment A11): **INTENT.md's frontmatter governs** and
|
||||
`layer.yaml` is a derived artifact that must be marked derived, must name
|
||||
INTENT.md as its source, and must agree with it. The sidecar is read anyway,
|
||||
because a disagreement between the two is itself a finding and is reported
|
||||
rather than resolved away by precedence.
|
||||
|
||||
Comparison against §3's closed four-token vocabulary ASCII-folds case before
|
||||
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).
|
||||
|
||||
Makes §11's second mechanical check real:
|
||||
|
||||
every direct Tooling client in a Staff repository maps to a declared
|
||||
§5.1, §5.2, or §5.3 entry
|
||||
|
|
@ -27,10 +42,59 @@ import yaml
|
|||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SRC = ROOT / "src" / "warden"
|
||||
INTENT = ROOT / "INTENT.md"
|
||||
DECL = ROOT / "layer.yaml"
|
||||
|
||||
VALID_SHAPES = {"5.1", "5.2", "5.3"}
|
||||
|
||||
# §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 —
|
||||
# omitting it is the defect A9 records against the estate's other validator.
|
||||
LAYER_VOCABULARY = {"taxonomy", "tooling", "engine", "staff"}
|
||||
|
||||
|
||||
def _fold(value: str) -> str:
|
||||
"""ASCII case-fold, per §3 as amended: two spellings of a token are one token."""
|
||||
return str(value).strip().encode("ascii", "ignore").decode().lower()
|
||||
|
||||
|
||||
def load_governing_layer() -> str:
|
||||
"""The declaration is INTENT.md's frontmatter `layer:` key (§11, GH-DEC-2026-017 §1).
|
||||
|
||||
layer.yaml is derived and does not govern. Read without a YAML frontmatter
|
||||
dependency: the file is read by humans first and a parser second.
|
||||
"""
|
||||
if not INTENT.exists():
|
||||
print(f"MISSING: {INTENT} — §11's governing declaration form")
|
||||
raise SystemExit(2)
|
||||
lines = INTENT.read_text().splitlines()
|
||||
if not lines or lines[0].strip() != "---":
|
||||
print("MALFORMED: INTENT.md has no frontmatter to carry the declaration (§11)")
|
||||
raise SystemExit(2)
|
||||
end = next((i for i, ln in enumerate(lines[1:], 1) if ln.strip() == "---"), None)
|
||||
if end is None:
|
||||
print("MALFORMED: INTENT.md frontmatter is not terminated")
|
||||
raise SystemExit(2)
|
||||
front = yaml.safe_load("\n".join(lines[1:end])) or {}
|
||||
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)
|
||||
layer = front["layer"]
|
||||
if _fold(layer) not in LAYER_VOCABULARY:
|
||||
print(
|
||||
f"MALFORMED: INTENT.md declares layer {layer!r}, outside §3's closed "
|
||||
f"vocabulary {sorted(LAYER_VOCABULARY)} (case-insensitive)"
|
||||
)
|
||||
raise SystemExit(2)
|
||||
return layer
|
||||
|
||||
# A direct Tooling contact is an *invocation*, not a mention. Matching the word
|
||||
# "bao" caught help text, a docstring, and the dev-tier doubles library that
|
||||
# simulates bao rather than calling it — three false positives on first run.
|
||||
|
|
@ -60,10 +124,33 @@ def load_declaration() -> dict:
|
|||
print(f"MISSING: {DECL} — ops-warden must declare in its own voice (§11)")
|
||||
raise SystemExit(2)
|
||||
decl = yaml.safe_load(DECL.read_text())
|
||||
for key in ("layer", "repository", "standard_version", "tooling_contacts"):
|
||||
for key in ("layer", "repository", "derived", "derived_from", "tooling_contacts"):
|
||||
if key not in decl:
|
||||
print(f"MALFORMED: layer.yaml has no {key!r}")
|
||||
raise SystemExit(2)
|
||||
# §11's derived-artifact rule: marked as derived, naming what it derives from.
|
||||
if decl["derived"] is not True:
|
||||
print("MALFORMED: layer.yaml must be marked 'derived: true' (§11, GH-DEC-2026-017 §1)")
|
||||
raise SystemExit(2)
|
||||
if decl["derived_from"] != "INTENT.md":
|
||||
print(
|
||||
f"MALFORMED: layer.yaml derives from {decl['derived_from']!r}; §11 names "
|
||||
"INTENT.md as the governing declaration"
|
||||
)
|
||||
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)
|
||||
if _fold(decl["layer"]) not in LAYER_VOCABULARY:
|
||||
print(
|
||||
f"MALFORMED: layer.yaml declares layer {decl['layer']!r}, outside §3's "
|
||||
f"closed vocabulary {sorted(LAYER_VOCABULARY)} (case-insensitive)"
|
||||
)
|
||||
raise SystemExit(2)
|
||||
for c in decl["tooling_contacts"]:
|
||||
if c.get("shape") not in VALID_SHAPES:
|
||||
print(f"MALFORMED: {c.get('id')} has shape {c.get('shape')!r}, not one of {sorted(VALID_SHAPES)}")
|
||||
|
|
@ -110,6 +197,7 @@ def main() -> int:
|
|||
ap.add_argument("--report", action="store_true", help="also print the declaration and gap review dates")
|
||||
args = ap.parse_args()
|
||||
|
||||
governing = load_governing_layer()
|
||||
decl = load_declaration()
|
||||
declared = {c["module"].split("/")[-1] for c in decl["tooling_contacts"]}
|
||||
excluded = _excluded(decl)
|
||||
|
|
@ -127,7 +215,8 @@ def main() -> int:
|
|||
stale_decls = declared - set(found) - voluntary
|
||||
|
||||
if args.report:
|
||||
print(f"{decl['repository']} — layer: {decl['layer']} (model v{decl['standard_version']})")
|
||||
print(f"{decl['repository']} — layer: {governing} (declared in INTENT.md; §11 governing form)")
|
||||
print(f" layer.yaml: derived from {decl['derived_from']}, layer: {decl['layer']}")
|
||||
print(f"declared by {decl['declared_by']}\n")
|
||||
for c in decl["tooling_contacts"]:
|
||||
line = f" §{c['shape']} {c['id']:<28} {c['module']}"
|
||||
|
|
@ -141,6 +230,21 @@ def main() -> int:
|
|||
print(f"\n{len(gaps)} declared gap(s) — tracked non-conformance, not conformance (§11).")
|
||||
|
||||
ok = True
|
||||
|
||||
# §11 as amended (A11): the derived form MUST agree with the governing one,
|
||||
# and a disagreement is a finding in its own right — reported, not resolved
|
||||
# away by precedence. Comparison folds case (A9): `Staff` and `staff` agree.
|
||||
if _fold(decl["layer"]) != _fold(governing):
|
||||
ok = False
|
||||
print(
|
||||
"\nDECLARATION DISAGREEMENT — a finding under §11, not a precedence question:\n"
|
||||
f" INTENT.md (governs): layer: {governing}\n"
|
||||
f" layer.yaml (derived): layer: {decl['layer']}\n"
|
||||
"Precedence says which value is ops-warden's answer. It does not say the\n"
|
||||
"disagreement did not happen. Case is already folded, so this is a real\n"
|
||||
"disagreement about a layer, not about orthography."
|
||||
)
|
||||
|
||||
if undeclared:
|
||||
ok = False
|
||||
print("\nUNDECLARED TOOLING CONTACT — a finding under §11, not a tracked gap:")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue