CI guards
A family of small scripts, each watching one rule, that run on every pull request. If any of them fails, the change cannot merge.
The gate and Landlock stop a bad action
while it happens. The CI guards stop it one step later: when the change tries to enter the main
branch. Each guard is a separate script in scripts/, written to check exactly one thing,
and each is wired into .github/workflows/operator-authority-checks.yml as a required
check. GitHub’s branch protection (see CODEOWNERS) refuses the merge
until every one of them passes.
The checks that run on every pull request
Section titled “The checks that run on every pull request”| Job | What it stops | Escape hatch |
|---|---|---|
policy-consistency |
The machine rulebook (AGENT_POLICY.yaml) and the human one (PROTECTED_PATHS.md) drifting apart. It loads the YAML and extracts every backticked path from the Markdown, then compares. |
None — fix the drift. |
changelog-updated |
Merging a change without a CHANGELOG.md entry (HARD RULE 8). |
None. |
sidebar-no-removal |
The dashboard sidebar quietly losing links, or new links being hidden behind adminOnly / feature flags (HARD RULE 7-bis). It counts the hrefs — the count may never go down. |
Write HR7-bis: confirmed in the PR description. |
operator-authority-tests |
Breaking the enforcement code itself. The full test suite for the gate, Landlock, manifests, the sweep, the shims and the check scripts must pass. | None. |
moth-no-write |
The worker-moth agent gaining any write capability (ADR 0115). A scanner looks for write operations in its code paths. | None. |
invariant-fitness-tests |
Breaking a numbered architecture invariant. Each invariant has a matching automated test (ADR 0118). | None. |
canonical-containers |
A new container appearing in a compose file without anyone deciding it should exist. New services must be on the allowlist in the policy. | Commit message token [allow-new-service]. |
no-agent-workflow-edits |
An agent editing the CI configuration that judges its own work. PRs authored by the bot accounts (cnysoho, cnry-morpheus) may not touch .github/workflows/. |
Commit message token [allow-workflow-edits]. |
pr-size-cap |
Pull requests too large to review honestly. The cap is 1,000 changed lines. | Commit message token [allow-large-pr]. |
existing-invariants |
Three older standing checks in one job: no OpenAI imports outside the adapter, no secret materialization patterns, and no legacy secret loaders in startup scripts. | None. |
Guards that run outside CI
Section titled “Guards that run outside CI”A few scripts in the same family run on the host or on demand rather than on pull requests:
check-process-secret-exposure.py— a runtime audit. It walks the environment and command line of live processes (and the env of every container) looking for secret-shaped values. It reports where a secret leaks, never the value itself, and keeps a small allowlist for harmless matches like broker URLs.check-release-versions.sh— keeps the version number inCHANGELOG.md,VERSION,pyproject.toml,__version__andpackage.jsonin lockstep, so a release can’t ship half-bumped.run-fast-path-regression-gate.sh— a performance tripwire: if message-ingestion latency regresses past a threshold, the run fails and the regression is on record.
What this layer is for
Section titled “What this layer is for”Every guard here repeats a rule that already exists somewhere else — in CLAUDE.md, in the invariants, in an ADR. That repetition is the point. The write-time layers can be bypassed by an agent running somewhere unexpected; a person can make the same mistake an agent would. The merge is the one chokepoint everything passes through, so the rules are checked once more there, by code that doesn’t get tired or distracted.

