Architecture invariants
Numbered properties the system must always hold — and the fitness tests that turn a paragraph of prose into a pass/fail CI check.
ARCHITECTURE_INVARIANTS.md (in the standards
folder) lists the things that must always be true, each with a stable identifier from
INV-001 to INV-027. They are Tier 0 — the highest authority short of a direct
operator instruction. Four of them sit directly behind hard rules:
INV-024 (secrets only on prontera), INV-025 (one brain, channels are thin), INV-026
(no AI attribution), and the newest — INV-027 (discovery precedes design; reuse before build) behind
HARD RULE 16. Not every invariant carries a fitness test, though: INV-027
is a process rule with no mechanical backstop (see the coverage map).
From markdown to a failing test
Section titled “From markdown to a failing test”Each invariant can carry a ### enforcement section containing a small block of
structured rules. The fitness-test harness turns those into running checks. The pipeline has four
stages:
ARCHITECTURE_INVARIANTS.md │ │ 1. loader — find every "## INV-NNN: Title" heading, │ then the first "### enforcement" block under it, │ then the first ```yaml fence inside that. ▼ list of rules (each rule is a dict with a "kind" field) │ │ 2. runner — one pytest case per rule (parametrized), │ so each failure is isolated and named INV-NNN/kind. ▼ 4 scanners 3. dispatch on "kind": │ • forbidden_pattern — regex must not match file contents │ • forbidden_dir — directory must not exist │ • forbidden_compose_service— no compose service name matches │ • forbidden_env_var — no compose env var matches a value ▼ findings ──▶ 4. any finding ⇒ pytest.fail ⇒ red build1 · The loader
Section titled “1 · The loader”The loader parses the markdown the same way a person reads it: every ## INV-NNN: Title
heading starts a new invariant; an optional ### enforcement sub-heading holds the machine
part; the first fenced yaml block under it is the list of rules. Invariants with no
enforcement block are kept as prose-only — they simply aren’t mechanically checked yet. The YAML must
be a list of dicts and each dict must have a kind, or the loader raises rather than
silently skipping.
2 · The runner
Section titled “2 · The runner”Every rule becomes its own pytest case, parametrized so a failure points at exactly one invariant
and one rule (the test id is INV-NNN/kind). Two guardrail tests sit alongside: one asserts
the markdown parses and every rule’s kind is known, and one asserts at least one
invariant still has an enforcement block — so if someone deletes the enforcement from the file, the
build notices the absence rather than going quietly green.
3 · The four scanners
Section titled “3 · The four scanners”Each rule’s kind selects one of four scanners. They are deliberately simple — stdlib
plus a YAML parser, no heavy framework:
forbidden_pattern— a regex that must not appear in the contents of files matching a glob (with an optional list of exception files).forbidden_dir— a directory that must not exist on disk (optionally only on named hosts).forbidden_compose_service— no service whose name matches a pattern may appear in the compose files. This is what fails the build on a new channel-worker service (HARD RULE 12 / INV-025).forbidden_env_var— a named environment variable in a compose file must not have a value matching a pattern.
4 · The verdict
Section titled “4 · The verdict”A scanner returns a list of findings; an empty list is a pass. Any finding calls
pytest.fail with the invariant id, the offending file and line, and the invariant’s stated
reason. The build goes red.
A worked example: INV-024
Section titled “A worked example: INV-024”INV-024 (“secrets live only on prontera”, the rule behind HARD
RULE 10) is the most-developed invariant, with all four scanner kinds. The neatest is its
forbidden_env_var rule, which uses a negative lookahead so that a broker
URL is allowed only if it points at prontera, and forbidden otherwise:
value_pattern: "^(?!.*prontera\.sole-augmented\.ts\.net).*$"In words: “match any value that does not contain the prontera host.” If a compose file ever sets the secret-broker URL to anything else, that regex matches, the scanner returns a finding, and the build fails — turning HARD RULE 10 from a paragraph into a wall.
Where invariants sit among the checkpoints
Section titled “Where invariants sit among the checkpoints”The fitness tests are the CI-time enforcement of the invariants. They run on the diff before it can merge, in the same family as the CODEOWNERS gate. They complement the write-time enforcement done by the gate and the kernel wall of Landlock: the gate stops a bad write as it happens; the fitness test stops a bad property from ever reaching the main branch. Same policy, different checkpoints.

