"""Structural validation of the shipped constitution source tree. The constitution is machine-parseable source (Article 1). These tests pin the structural contract the tooling depends on: ten kernel articles, parseable invariants and userland modules, a semver version file, and a well-formed citizen registry. """ from __future__ import annotations import yaml from tests.helpers import PROJECT_ROOT, find_semver CONSTITUTION = PROJECT_ROOT / "constitution" def _load(path): doc = yaml.safe_load(path.read_text(encoding="utf-8")) assert isinstance(doc, dict) and doc, f"{path.name} must parse to a non-empty mapping" return doc def test_kernel_has_exactly_ten_articles(): articles = sorted((CONSTITUTION / "kernel").glob("*.yaml")) assert len(articles) == 10, [p.name for p in articles] def test_kernel_articles_are_numbered_and_parse(): articles = sorted((CONSTITUTION / "kernel").glob("*.yaml")) for index, path in enumerate(articles, start=1): assert f"article-{index:02d}" in path.name, ( f"kernel articles must be numbered sequentially; {path.name} is out of order" ) _load(path) def test_kernel_articles_have_human_titles(): for path in (CONSTITUTION / "kernel").glob("*.yaml"): doc = _load(path) title = doc.get("title") or doc.get("name") assert isinstance(title, str) and title.strip(), f"{path.name} needs a title" def test_version_file_declares_semver(): doc = _load(CONSTITUTION / "version.yaml") versions = find_semver(doc) assert versions, "version.yaml must contain a semantic version string" def test_invariants_file_parses_and_is_nonempty(): doc = _load(CONSTITUTION / "invariants.yaml") # The invariants document must enumerate at least a handful of them. flattened = str(doc).lower() assert len(flattened) > 100, "invariants.yaml looks suspiciously empty" def test_userland_modules_parse(): modules = sorted((CONSTITUTION / "userland").glob("*.yaml")) assert modules, "at least one userland module (the funding pool) must ship" for path in modules: _load(path) def test_funding_pool_module_exists(): assert (CONSTITUTION / "userland" / "funding-pool.yaml").exists() def test_citizen_registry_parses(): doc = _load(PROJECT_ROOT / "citizens" / "registry.yaml") def find_citizen_list(node): if isinstance(node, list) and node and all(isinstance(i, dict) for i in node): if any("id" in i or "name" in i for i in node): return node if isinstance(node, dict): for value in node.values(): found = find_citizen_list(value) if found is not None: return found return None citizens = find_citizen_list(doc) assert citizens is not None, "registry.yaml must contain a list of citizen records" def test_no_capital_weighting_anywhere_in_kernel(): """One person, one vote: the kernel must never weight votes by stake.""" for path in (CONSTITUTION / "kernel").glob("*.yaml"): text = path.read_text(encoding="utf-8").lower() for forbidden in ("token-weighted", "stake-weighted", "capital-weighted", "one token one vote"): assert forbidden not in text, f"{path.name} contains forbidden weighting {forbidden!r}"