yams/tests/scripts/check_configuration_authority.py
Trevon 6b5b6647bd
[04/14] Repository hygiene and reviewable configuration/retrieval contracts (#144)
* chore(repo): land the retrieval contract and drop root cruft

Lands work that had been sitting uncommitted in the working tree:

- docs/architecture/retrieval_contracts.md plus its executable form,
  tests/benchmarks/retrieval_contract.py and test_retrieval_contract.py,
  now registered in meson as retrieval_contract_unit (suite: policy).
  .gitignore keeps them tracked beneath the tests/benchmarks/*.py ignore.
- AGENTS.md: the Development Memory section, and the product default
  recorded as hybrid_assist + shadow with topology-off as the control,
  which is what search_topology_stage already does.
  docs/benchmarks/index.md gains the matching search_shadow_cost plan.
- .gitleaks.toml, and a Secret scan workflow that actually runs it on
  push and pull requests (nothing in .github invoked gitleaks before).

Deletes three root files with zero references anywhere in the tree:
bench_profile.json (ad-hoc profiling leftover), CppProperties.json
(Visual Studio config; the repo standardises on Meson), and spdlog.pc
(a hand-copied spdlog 1.12 pkg-config with prefix=/usr/local that would
mislead any PKG_CONFIG_PATH lookup; spdlog comes from Conan).

docs/plans/ (two p2p designs already shipped in 5a53cdfa and d012d95b)
was ingested into YAMS with task=desloppification source=plan, hydrated
via yams cat and byte-compared before removal, per the new AGENTS.md
rule; tests/scripts/analyze_simeon_adaptivity.py no longer points at a
plans directory.

Also reflows two stale line anchors in raw_environment_allowlist.txt
for tools/yams-cli/main.cpp (shifted by 11c39157) so the policy suite
passes again; no new environment writes.

Not included: the external/yams-repo submodule pointer in the working
tree was a stale local clone two commits behind, not an intended bump.

Signed-off-by: trvon <me@trevon.dev>

* test(policy): make the configuration-authority ratchet bidirectional

check_configuration_authority.py only reported keys and TOML readers
present in code but missing from the allowlists, so the reviewed
YAMS_* surface could grow but never shrink: production_environment_keys.txt
even said removals "may remain grandfathered". An allowlist that only
accretes stops describing the code.

The policy now also fails on allowlist entries with no remaining
occurrence in src/, include/, or tools/, naming the lines to delete.
Key removals in later commits therefore have to update the allowlist in
the same change, and the count in the success banner becomes a real
measure of the environment surface (432 today).

stale_entries() exposes the two stale sets for tooling; three unit
tests cover stale key, stale reader, and the returned names.

Signed-off-by: trvon <me@trevon.dev>

* tools(policy): report where every configuration key is referenced

Adds tests/scripts/report_config_key_usage.py: for each YAMS_* key in
production_environment_keys.txt and each dotted TOML key literally
resolved in ConfigResolver.cpp, count whole-token references per tree
bucket (src, test, bench, docs, plugin; build output and the allowlists
themselves excluded) and assign a verdict: KEEP when anything outside
product code exercises or documents the key, CANDIDATE when only
product code mentions it, NOT_IN_SRC when the allowlist is stale.

The report is evidence, not a decision. From here on a key deletion
must paste its CANDIDATE rows into the change description; the first
audit pass hand-listed keys that turned out to have bench and test
consumers, which is exactly the mistake a mechanical inventory avoids.

Today: 432 env keys (215 CANDIDATE, 217 KEEP), 117 TOML keys
(103 CANDIDATE, 14 KEEP). Registered as config_key_usage_report_unit.

The report counts only files git tracks (git ls-files) when the root is a
work tree, so an ignored local bench harness cannot turn a CANDIDATE into a
KEEP on one machine and not another; outside a work tree it falls back to
scanning the directory, which is what the synthetic-tree test exercises.

Signed-off-by: trvon <me@trevon.dev>

---------

Signed-off-by: trvon <me@trevon.dev>
2026-09-12 10:09:18 -04:00

151 lines
5.1 KiB
Python

#!/usr/bin/env python3
"""Fail on new production YAMS_* surfaces or duplicate TOML reader definitions.
The allowlists are a ratchet in both directions: an entry whose key or reader no
longer exists in the source tree fails too, so the reviewed surface can only shrink.
"""
from __future__ import annotations
import argparse
import re
import sys
from pathlib import Path
SOURCE_ROOTS = ("src", "include", "tools")
SOURCE_SUFFIXES = {".c", ".cc", ".cpp", ".cxx", ".h", ".hh", ".hpp"}
ENV_LITERAL_RE = re.compile(r"[\"'](YAMS_[A-Z0-9_]+)[\"']")
TOML_DEFINITION_RE = re.compile(
r"(?P<name>[A-Za-z_]\w*(?:[Tt][Oo][Mm][Ll])\w*)\s*"
r"\([^;{}]*\)\s*(?:const\s*)?\{",
re.MULTILINE,
)
def iter_sources(root: Path):
for relative_root in SOURCE_ROOTS:
source_root = root / relative_root
if not source_root.is_dir():
continue
for path in source_root.rglob("*"):
if path.is_file() and path.suffix.lower() in SOURCE_SUFFIXES:
yield path
def read_allowlist(path: Path) -> set[str]:
return {
line.strip()
for line in path.read_text(encoding="utf-8").splitlines()
if line.strip() and not line.lstrip().startswith("#")
}
def production_environment_keys(root: Path) -> set[str]:
keys: set[str] = set()
for path in iter_sources(root):
keys.update(
ENV_LITERAL_RE.findall(path.read_text(encoding="utf-8", errors="ignore"))
)
return keys
def toml_reader_definitions(root: Path) -> set[str]:
definitions: set[str] = set()
for path in iter_sources(root):
if path.suffix.lower() in {".h", ".hh", ".hpp"}:
continue
text = path.read_text(encoding="utf-8", errors="ignore")
for match in TOML_DEFINITION_RE.finditer(text):
line = text.count("\n", 0, match.start()) + 1
relative = path.relative_to(root).as_posix()
definitions.add(f"{relative}:{match.group('name')}:{line}")
return definitions
def normalized_definition(entry: str) -> str:
path, name, _line = entry.rsplit(":", 2)
return f"{path}:{name}"
def stale_entries(
root: Path, environment_allowlist: Path, reader_allowlist: Path
) -> tuple[list[str], list[str]]:
"""Allowlist entries with no remaining occurrence in the source tree."""
allowed_keys = read_allowlist(environment_allowlist)
current_keys = production_environment_keys(root)
allowed_readers = read_allowlist(reader_allowlist)
current_readers = {
normalized_definition(definition) for definition in toml_reader_definitions(root)
}
return sorted(allowed_keys - current_keys), sorted(allowed_readers - current_readers)
def run(root: Path, environment_allowlist: Path, reader_allowlist: Path) -> int:
allowed_keys = read_allowlist(environment_allowlist)
current_keys = production_environment_keys(root)
unknown_keys = sorted(current_keys - allowed_keys)
stale_keys = sorted(allowed_keys - current_keys)
allowed_readers = read_allowlist(reader_allowlist)
definitions = sorted(toml_reader_definitions(root))
unknown_readers = [
definition
for definition in definitions
if normalized_definition(definition) not in allowed_readers
]
current_readers = {normalized_definition(definition) for definition in definitions}
stale_readers = sorted(allowed_readers - current_readers)
if unknown_keys:
print(
"new production YAMS_* literals require typed-config review:",
file=sys.stderr,
)
for key in unknown_keys:
print(f" {key}", file=sys.stderr)
if unknown_readers:
print(
"new TOML reader definitions must use parse_simple_toml:", file=sys.stderr
)
for definition in unknown_readers:
print(f" {definition}", file=sys.stderr)
if stale_keys:
print(
f"stale YAMS_* entries: delete these lines from {environment_allowlist.name}:",
file=sys.stderr,
)
for key in stale_keys:
print(f" {key}", file=sys.stderr)
if stale_readers:
print(
f"stale TOML reader entries: delete these lines from {reader_allowlist.name}:",
file=sys.stderr,
)
for definition in stale_readers:
print(f" {definition}", file=sys.stderr)
if unknown_keys or unknown_readers or stale_keys or stale_readers:
return 1
print(
"configuration authority policy: "
f"{len(current_keys)} reviewed YAMS_* literal(s), "
f"{len(definitions)} reviewed TOML reader definition(s), 0 new, 0 stale"
)
return 0
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--environment-allowlist", type=Path, required=True)
parser.add_argument("--reader-allowlist", type=Path, required=True)
args = parser.parse_args()
return run(
args.root.resolve(),
args.environment_allowlist.resolve(),
args.reader_allowlist.resolve(),
)
if __name__ == "__main__":
raise SystemExit(main())