Skip to content

CI gates

The cheapest way to build a system that looks safe is to add checks nobody has ever watched fail. They cost minutes of pipeline time, they turn green on every run, and they are load-bearing in exactly one respect: everyone downstream believes them. The estate’s answer is a rule that a gate ships with a self-test that proves it red — a deliberately broken fixture the gate is required to reject — and that the self-test runs in CI, on the same run that trusts the gate.

CI gate map — 104 scripts across 102 pipelines

Snapshot taken — build-time, not live
  • 102pipeline definitions
  • 74are checks
  • 26ship a self-test
  • 24proven red by CI
104 of 104
ProofScriptWhat it asserts
self-test onlyado_pipeline_metrics.pyansible/scripts/ · arronpitman-siteado_pipeline_metrics.py — the ONE collector for ADO pipeline queue/run timing.
proven redado_pipeline_run.pyansible/scripts/ · ansible-ciTrigger or wait on an ADO pipeline run (Epic #376, #923, #1824).
proven redado_to_actions.pyansible/scripts/ · ansible-ciConvert Azure DevOps pipeline YAML into GitHub Actions workflows, deterministically.
proven redagent_access_conformance_gate.pyansible/scripts/ · ansible-ciConformance gate over the register of AGENT-OPERATED SYSTEMS — Epic #2488, Issue #2518.
proven redci_secret_parity_probe.pyansible/scripts/ · ansible-ci-secret-parityci_secret_parity_probe.py — prove a GitHub Actions job resolves the SAME credentials as an ADO agent job on the same runner (Epic #2282, Issue #2285, acceptance criterion 3).
proven redcheck_docs_toolchain_pins.pyansible/scripts/doc_gen/ · pitlab-docscheck_docs_toolchain_pins.py — pitlab-docs MkDocs toolchain pin-parity gate (Issue #2186).
nonecheck_exposure_register.pyansible/scripts/doc_gen/ · pitlab-docscheck_exposure_register.py — fail the docs build if an un-gated (posture-d) row on the External Exposure Register points at a vanished link target (Issue #1705, Epic #938).
nonegenerate_cloudflare_docs.pyansible/scripts/doc_gen/ · pitlab-docsCloudflare Access Map generator.
nonegenerate_docker_docs.pyansible/scripts/doc_gen/ · pitlab-docsDocker stacks documentation generator.
nonegenerate_room_automations.pyansible/scripts/doc_gen/ · hass-configPer-room "day in the life" pages, generated from hass-config.
nonegenerate_schedule_docs.pyansible/scripts/doc_gen/ · pitlab-docsMaintenance schedule documentation generator.
nonegenerate_service_deps.pyansible/scripts/doc_gen/ · pitlab-docsService dependency map generator — ONE derivation, THREE renders (Epic #2260, ADR-0355).
nonegenerate_tf_docs.pyansible/scripts/doc_gen/ · 7 pipelinesTerraform documentation generator.
proven redpublic_scrub_gate.pyansible/scripts/doc_gen/ · 2 pipelinesFail-closed scrub gate for pages published to the public showcase site (Epic #2557, Issue #2559).
nonestandards_enforcement_gate.pyansible/scripts/doc_gen/ · 2 pipelinesStandard-Enforcement meta-gate (Epic #1713, Issue #1715, ADR-0176).
nonetest_check_exposure_register.pyansible/scripts/doc_gen/ · pitlab-docsProven-red regression for check_exposure_register.py (ADR-0141).
nonetest_check_standards_completeness.pyansible/scripts/doc_gen/ · pitlab-docsRegression + negative-control test for check_standards_completeness.py (Epic #1996, Issue #1997 — Build-Hook & Pipeline-Gate Test Standard, ADR-0141, PD12).
nonetest_validate_compliance_catalogue.pyansible/scripts/doc_gen/ · ansible-ciRegression + negative-control test for validate_compliance_catalogue.py (Epic #2247, Issue #2249 — Build-Hook & Pipeline-Gate Test Standard, ADR-0141, PD12).
nonetest_validate_script_observability.pyansible/scripts/doc_gen/ · ansible-ciCommitted regression test for validate_script_observability.py (Build-Hook & Pipeline-Gate Test Standard, ADR-0141 / ADR-0219).
nonetest_validate_standards_taxonomy.pyansible/scripts/doc_gen/ · pitlab-docsRegression + negative-control test for validate_standards_taxonomy.py (Epic #1996, Issue #1997 — Build-Hook & Pipeline-Gate Test Standard, ADR-0141, PD12).
proven redvalidate_adr_numbers.pyansible/scripts/doc_gen/ · pitlab-docsno module docstring
proven redvalidate_bin_manifest.pyansible/scripts/doc_gen/ · ansible-ciValidate the control01 /usr/local/bin deploy manifests (Epic #2386).
nonevalidate_compliance_catalogue.pyansible/scripts/doc_gen/ · ansible-ciCompliance control-catalogue resolution gate (Epic #2247, Issue #2249, ADR-0352).
nonevalidate_docker01_cac.pyansible/scripts/doc_gen/ · ansible-standards-enforcement-reconciliationdocker01 config-as-code conformance gate (Epic #886, Issue #2002).
nonevalidate_docs_published.pyansible/scripts/doc_gen/ · pitlab-docsBuild-time guard: every hand-authored doc in pitlab-docs must reach the site.
nonevalidate_notification_catalog.pyansible/scripts/doc_gen/ · ansible-ciStatic Notification-Catalog guard (Epic #1275, Issue #1278, ADR-0062).
nonevalidate_overview_hubs.pyansible/scripts/doc_gen/ · pitlab-docsBlocking structural lint for overview-hub docs (ADR-0113, Documentation Architecture Standard).
nonevalidate_pipeline_path_coverage.pyansible/scripts/doc_gen/ · ansible-ciCI guard: every pipeline's trigger paths cover the files its playbook actually consumes.
nonevalidate_schedule_tz.pyansible/scripts/doc_gen/ · ansible-ciStatic Timezone-Standard guard for pitlab host schedules (Epic #1270, Issue #1272).
nonevalidate_script_observability.pyansible/scripts/doc_gen/ · ansible-ciRatcheting unattended-script observability gate (ADR-0219, Epic #1852, Issue #1848).
nonevalidate_standards_taxonomy.pyansible/scripts/doc_gen/ · pitlab-docsStandards-taxonomy gate (Epic #1996, Issue #1997, ADR-0252).
nonevalidate_systemd_selfheal.pyansible/scripts/doc_gen/ · ansible-standards-enforcement-reconciliationsystemd self-heal clean-reap guard (Epic #1921, Issue #1925, ADR-0234).
proven redvalidate_userparam_barrier.pyansible/scripts/doc_gen/ · ansible-civalidate_userparam_barrier.py — a NEW Zabbix UserParameter must be written ABOVE the `meta: flush_handlers` barrier in playbooks/sync_control01.yml.
proven redgithub_schedule_watchdog.pyansible/scripts/ · ansible-ciFreshness watchdog for GitHub Actions scheduled workflows.
proven redgroom_backlog_debt.pyansible/scripts/ · ansible-control01-syncgroom_backlog_debt.py — the backlog-grooming debt detective (Epic #1865, Issue #2476, ADR-0399).
proven redha_entity_name_conformance.pyansible/scripts/ · ansible-control01-syncha_entity_name_conformance.py — assert every Home Assistant friendly_name is formatted so the Assist conversation agent can actually match it.
proven redha_press_detector.pyansible/scripts/ · ansible-control01-syncha_press_detector.py — catch a silent Zigbee button break within minutes of use.
noneinfisical_env.pyansible/scripts/ · arronpitman-siteFetch-on-login interactive env for control01 (Epic #376, Issue #925 — Phase 4).
noneinfisical_fetch_env.pyansible/scripts/ · 3 pipelinesFetch a stack's secrets from Infisical and emit them as .env lines (Epic #376).
noneinfisical_tf_vars.pyansible/scripts/ · 6 pipelinesInject Infisical secrets into a Terraform ADO pipeline job as TF_VAR_* (Epic #376, Issue #926 — Phase 5).
noneloki_push.pyansible/scripts/ · ansible-standards-enforcement-reconciliationPush a single structured log line to Loki (Epic #376, #923).
nonepatch_reboot_coordinator.pyansible/scripts/ · ansible-cipatch_reboot_coordinator.py — pitlab fleet PATCH+reboot coordinator (Epic #1769, Issue #1771).
nonepitlab-onboarding.shansible/scripts/ · 2 pipelinesno module docstring
nonepushover_notify.pyansible/scripts/ · 3 pipelinesSend a Pushover notification (Epic #376, #925).
nonesecret_scan.shansible/scripts/ · 10 pipelinesno module docstring
nonetest_ado_pipeline_run.pyansible/scripts/ · ansible-control01-syncRegression gate for ado_pipeline_run.py's wait-path hardening (Issue #2210, ADR-0339).
nonetest_freescout_distill.pyansible/scripts/ · ansible-control01-syncSelf-test for freescout_distill.py — stdlib only, no network, no live LLM/Qdrant/FreeScout.
nonetest_ha_ownership_anomaly.pyansible/scripts/ · ansible-control01-syncProven-red regression for ha_ownership_anomaly.py (ADR-0141 discipline, Issue #2328).
nonetest_haos_loki_logger.pyansible/scripts/ · ansible-deploy-haos-lokiOffline liveness self-test for the HAOS loki_logger custom component (Issue #2064).
nonetest_stalled_grab_watchdog.pyansible/scripts/ · ansible-control01-syncSelf-test for stalled_grab_watchdog.py — stdlib only, no network, no live *arr.
self-test onlytest_stuck_alert_watchdog.pyansible/scripts/ · ansible-control01-syncDiscrimination proof for the stuck-alert watchdog (Epic #2107, Issue #2158).
nonetest_zabbix_cron_heartbeats.pyansible/scripts/ · ansible-control01-syncSelf-test for zabbix_cron_heartbeats_monitoring.py — stdlib only, no network, no live Zabbix.
proven redvalidate_ci_pool_parity.pyansible/scripts/ · ansible-civalidate_ci_pool_parity.py — assert every agent in the pitlab pool carries the SAME, DECLARED toolchain (Epic #2187, Issue #2206; design docs/designs/2187-ci-runner-pool.md).
proven redvalidate_deploy_tags.pyansible/scripts/ · ansible-civalidate_deploy_tags.py — conformance gate for the stack-deploy tag taxonomy.
proven redvalidate_dt_project_namespaces.pyansible/scripts/ · ansible-civalidate_dt_project_namespaces.py — the conformance gate for per-host Dependency-Track project namespacing (Issue #2121, ADR-0363).
proven redvalidate_guard_ledger.pyansible/scripts/ · ansible-ciAggregating verdict gate for a multi-guard CI job (incident #2470).
proven redvalidate_handler_durability.pyansible/scripts/ · ansible-civalidate_handler_durability.py — conformance gate for pending-handler durability.
proven redvalidate_pipeline_agent_portability.pyansible/scripts/ · ansible-civalidate_pipeline_agent_portability.py — the conformance gate for pipeline agent-portability (Epic #2187, Issue #2216, ADR-0337).
proven redvalidate_repo_script_locality.pyansible/scripts/ · ansible-civalidate_repo_script_locality.py — conformance gate for repo-script execution locality.
proven redvalidate_secret_scan_coverage.pyansible/scripts/ · ansible-standards-enforcement-reconciliationvalidate_secret_scan_coverage.py — fleet-wide secret-scanning conformance gate (ADR-0277).
self-test onlyvalidate_target_lock_coverage.pyansible/scripts/ · ansible-civalidate_target_lock_coverage.py — the conformance gate for target-host serialisation (Issue #2199 step 7, ADR-0330).
proven redwaitfor_poll.pyansible/scripts/ · ansible-ciwaitfor poller — evaluate a TYPED predicate to a terminal state, always leaving a marker.
nonezabbix_monitoring_reconciler.pyansible/scripts/ · ansible-standards-enforcement-reconciliationMonitoring-as-Code drift audit — the live half of the Zabbix config-as-code loop (Epic #833, Issue #1523).
noneassert_rendered.mjsarronpitman-site/scripts/ · arronpitman-siteRendered-DOM acceptance for the four set-pieces (Epic #2557, Issue #2560).
proven redbuild_snapshots.pyarronpitman-site/scripts/ · arronpitman-siteEmit the build-time data snapshots the four set-pieces render (Epic #2557, Issue #2560).
nonelegibility_gate.mjsarronpitman-site/scripts/ · arronpitman-siteDiagram legibility gate for the published site (Epic #2591, Issue #2593).
nonelighthouse_gate.mjsarronpitman-site/scripts/ · arronpitman-siteLighthouse gate for the published site (Epic #2557, Issue #2560).
proven redprerender_mermaid.mjsarronpitman-site/scripts/ · arronpitman-sitePre-render every Mermaid diagram in the site's content to static SVG, at build time, in both colour schemes (Epic #2591, Issue #2593; ADR-0456, which supersedes ADR-0028's rejection of SVG pre-render).
self-test onlyprove_setpiece_scrub.sharronpitman-site/scripts/ · arronpitman-siteno module docstring
proven redrender_corpus.pyarronpitman-site/scripts/ · arronpitman-siteSelect and render the `public: true` slice of the pitlab-docs corpus as Starlight pages.
proven redrule_inventory_gate.pyclaude-config/scripts/ · claude-config-ciRule-inventory gate for the claude-config constitution (Epic #2420, Issue #2421).
proven redartifact_gate.pydocker-stacks/scripts/ · docker-stacks-observabilityArtifact acceptance gate for RUN-TO-COMPLETION workloads (Issue #2181, ADR-0321).
proven redchanged_image_trivy_gate.pydocker-stacks/scripts/ · docker-stacks-secret-scanchanged_image_trivy_gate.py — block a docker-stacks push that bumps an image pin to a tag carrying a CRITICAL vulnerability.
proven redcounter_birth_guard.pydocker-stacks/scripts/ · docker-stacks-observabilitycounter_birth_guard.py — static CI gate against the counter-birth false-page class (ADR-0292).
noneeit_conformance_gate.pydocker-stacks/scripts/ · 6 pipelinesEncryption-in-Transit conformance gate — fails a deploy when a NEW plaintext cross-host listener appears on docker01 that is not accounted for on the exceptions register.
proven redgate_common.pydocker-stacks/scripts/ · 5 pipelinesShared helpers for the docker-stacks post-deploy gates (Issue #2185, ADR-0317).
nonehomepage_icon_gate.pydocker-stacks/scripts/ · docker-stacks-infraPre-deploy icon gate — fails the homepage deploy if any tile icon does not resolve to a real image, so the start page can never ship a generic "?" placeholder.
nonehomepage_regen_parity_gate.pydocker-stacks/scripts/ · docker-stacks-infrahomepage_regen_parity_gate.py — fail the deploy when stacks/homepage/config/services.yaml is not what its generator would produce from its sources (Epic #1594, Issue #1967; ADR-0143).
proven redhost_stack_source_gate.pydocker-stacks/scripts/ · docker-stacks-infraHost->repo stack-source reconciliation gate — every workload running on docker01 must have source.
noneloki_log_gate.pydocker-stacks/scripts/ · 6 pipelinesPost-deploy Loki log-shipping gate — fails the deploy if a just-deployed stack ships NO logs to Loki.
proven redpipeline_coverage_gate.pydocker-stacks/scripts/ · 6 pipelinesPipeline stack-list completeness gate — every deployed stack must be gated and triggered.
nonequiet_hours_guard.pydocker-stacks/scripts/ · docker-stacks-observabilityquiet_hours_guard.py — static stuck-mute CI gate for the sleep quiet-hours window (ADR-0264).
nonerefresh_consumer_roots.shdocker-stacks/scripts/ · 6 pipelinesno module docstring
proven redrenovate_config_gate.pydocker-stacks/scripts/ · 3 pipelinesrenovate_config_gate.py — semantic CI gate over renovate.json (Issue #2150).
nonesmoke_gate.pydocker-stacks/scripts/ · 6 pipelinesPre-deploy smoke gate — fails the deploy if a just-deployed container does not start & serve.
nonetest_eit_conformance_gate.pydocker-stacks/scripts/ · ansible-eit-reconciliationSelf-test for eit_conformance_gate.py — stdlib only, no network, no ssh.
proven redtestplan_gate.pydocker-stacks/scripts/ · 7 pipelinesPost-deploy service test-plan gate — runs each deployed stack's test plan, fails the pipeline on a functional regression, and (mode-gated) AUTO-ROLLS-BACK the offending deploy to last-good (Service Test Plan Standard, ADR-0102; Issues #1478 gate + #1479 auto-rollback).
self-test onlytestplan_run.pydocker-stacks/scripts/ · 7 pipelinesShared service test-plan runner — the one runner behind the Service Test Plan Standard (ADR-0102).
proven redtestplan_synthetic_gate.pydocker-stacks/scripts/ · docker-stacks-infraScheduled synthetic test-plan gate for host/LXC services (Service Test Plan Standard, ADR-0102; host/LXC tranche, Issue #1489).
nonecheck_dashboard_conformance.pydocker-stacks/stacks/observability/scripts/ · docker-stacks-observabilityDashboard conformance gate — enforces Pillar 2 + the bidirectional catalog at deploy time.
noneplan_classifier_gate.pytf-azure/scripts/ · 2 pipelinesplan_classifier_gate.py — decide whether a tf-azure apply may run UNATTENDED or must pause for Pit's approval.
nonetest_plan_classifier_gate.pytf-azure/scripts/ · 2 pipelinesRegression test for plan_classifier_gate.py (ADR-0141 — build-hook/gate test standard).
noneplan_classifier_gate.pytf-backblaze/scripts/ · tf-backblazeplan_classifier_gate.py — decide whether a tf-backblaze apply may run UNATTENDED or must pause for Pit's approval.
nonetest_plan_classifier_gate.pytf-backblaze/scripts/ · tf-backblazeRegression test for plan_classifier_gate.py (ADR-0141 — build-hook/gate test standard).
noneconfig_completeness_gate.pytf-cloudflare/scripts/ · tf-cloudflareconfig_completeness_gate.py — fail the tf-cloudflare plan when a LIVE Cloudflare object is absent from terraform state and not on the ratified completeness allowlist (Issue #2040, ADR-0259 follow-up).
noneexposure_conformance_gate.pytf-cloudflare/scripts/ · tf-cloudflareexposure_conformance_gate.py — fail the tf-cloudflare plan on an un-gated, unregistered public hostname (RULE 13 / ADR-0150).
noneplan_classifier_gate.pytf-cloudflare/scripts/ · tf-cloudflareplan_classifier_gate.py — decide whether a tf-cloudflare apply may run UNATTENDED or must pause for Arron's manual approval (Epic #2057, RULE 14 scoped carve-out / ADR-0268).
nonetest_config_completeness_gate.pytf-cloudflare/scripts/ · tf-cloudflareRegression test for config_completeness_gate.py (ADR-0141 — build-hook/gate test standard).
nonetest_exposure_conformance_gate.pytf-cloudflare/scripts/ · tf-cloudflareRegression test for exposure_conformance_gate.py (ADR-0141 — build-hook/gate test standard).
nonetest_plan_classifier_gate.pytf-cloudflare/scripts/ · tf-cloudflareRegression test for plan_classifier_gate.py (ADR-0141 — build-hook/gate test standard).
noneplan_classifier_gate.pytf-proxmox/scripts/ · 2 pipelinesplan_classifier_gate.py — decide whether a tf-proxmox apply may run UNATTENDED or must pause for Pit's approval.
nonetest_plan_classifier_gate.pytf-proxmox/scripts/ · 2 pipelinesRegression test for plan_classifier_gate.py (ADR-0141 — build-hook/gate test standard).
noneplan_classifier_gate.pytf-tailscale/scripts/ · tf-tailscaleplan_classifier_gate.py — decide whether a tf-tailscale apply may run UNATTENDED or must pause for Pit's approval.
nonetest_plan_classifier_gate.pytf-tailscale/scripts/ · tf-tailscaleRegression test for plan_classifier_gate.py (ADR-0141 — build-hook/gate test standard).

32% of the checks are proven red by CI — that is,24 of 74 are run against a deliberately broken fixture on the same run that trusts them, and are required to fail. The rest are not, and that is the honest state of it rather than a rounded-up one. A gate nobody has seen go red is a green light nobody earned.

Derived, not listed: all 102 pipeline definitions were read from the build API, 60 of them run at least one repository script, and every one of those scripts was fetched and read for its own description. Every one resolved to a file.A script counts as a check when its filename declares it one —validate_, assert_, verify_, check_,test_, or a _gate/_guard/_conformancesuffix — which is this estate's own convention. A builder or a credential helper is listed and not counted.

Why “proven red” is a different column from “has a self-test”

Section titled “Why “proven red” is a different column from “has a self-test””

They are deliberately separate, because collapsing them hides the interesting state. A self-test that exists and is never run is a gate nobody has seen go red; it has the shape of proof and none of the effect. Splitting the columns makes that state visible instead of rounding it up into the reassuring one.

The number that is not 100% is the honest part of this panel. Some of these checks are proved by hand at the time they are written and never again; that is a real gap, it is visible here, and publishing it is cheaper than the alternative, which is discovering it during an incident.

Nothing here is typed in. All the project’s pipeline definitions are read from the build API, each one’s YAML is read from the repository it builds from, and every script that YAML runs is read for its own opening description. If a single definition cannot be resolved, the build fails rather than publishing a partial census — a smaller number presented with the same confidence is worse than no number, because nothing on the page could tell you which you were looking at. A hand-written list would be the specific failure this estate names authored, not observed: every entry correct, and the set silently short of whatever was added after the list was written.

Three things had to be got right before the list was trustworthy, and each was wrong first:

  • The credential could read three of the hundred pipeline definitions. Reading everything through the API looked like the thorough choice, and the build identity’s authorisation is scoped to the repositories its own pipeline references — so the first published version of this panel covered 30 scripts and presented them with exactly the same confidence as the full set. The page’s own numbers agreed with the data behind it perfectly; only an absolute floor in the acceptance gate caught it, because an equality check between two consistent wrong numbers cannot. It now reads from the build agent’s own checkouts, which carry every repository, and refuses to publish at all if any definition is unreadable.
  • Anchoring on an interpreter keywordpython3 …, node … — found the tidy invocations and missed the strictest gates on this very site, which are handed to a container image’s own entry point. Their absence looked exactly like “this pipeline has no rendered-DOM gate”.
  • A step’s display name comes after the shell block it names, so attributing scripts to the last label seen shifts every step by one. It does not fail; it produces a complete, plausible, wrong map.

A script counts when its filename declares it one — validate_, assert_, verify_, check_, test_, or a _gate / _guard / _conformance suffix. That is this estate’s own naming convention rather than a judgement made here, and stating the rule on the page is what makes a miscount a visible disagreement with something published rather than an invisible opinion. A builder or a credential helper is listed and not counted.