Skip to content

Prove the gates a positive control cannot reach - #238

Merged
stxkxs merged 9 commits into
mainfrom
prove-the-control-exempt-gates
Sep 5, 2026
Merged

Prove the gates a positive control cannot reach#238
stxkxs merged 9 commits into
mainfrom
prove-the-control-exempt-gates

Conversation

@stxkxs

@stxkxs stxkxs commented Sep 2, 2026

Copy link
Copy Markdown
Member

Closes the standing REJECT that capped testing at D: six gate scripts carrying
neither unit coverage nor a positive control.

Which verdicts are proved, and which are only covered

A verdict is proved when a violation is planted and the assertion that names
it fails. It is covered when tests exercise it but nothing plants the
violation the verdict exists to catch — asserting that a gate reports nothing on
a healthy tree is a control against false positives, satisfied by return [].

Verdict State
check-policy-admission.judge / judge_runtime_pod proved — 4 planted mutants, 8 named tests
check-policy-admission.check_exclusion_parity proved — 2 planted mutants, 8 named tests
validate-dashboards.check_local_dashboards proved — 1 planted mutant, 5 named tests; each of its 3 detections and its anti-vacuity floor planted separately
check-image-pins.classify / verdict proved — 2 planted mutants, 4 named tests
render-addons.registry_answered / _path_from_valuefiles / oci_ref proved — 3 planted mutants, 3 named tests
check-log-volume-budget.environment_verdict / alert_threshold proved — 2 planted mutants, 3 named tests
check-platform-crs.walk (types, required, list identity) proved — 3 planted mutants, 5 named tests
check-policy-admission.check_namespace_coverage covered — asserted both ways on supplied sets, no planted mutant
check-policy-admission._prepare, _rule_key proved — 2 planted mutants, 2 named tests
validate-dashboards extractors (template_vars, alert_panels, wired_datasource_refs) proved — 3 planted mutants, 7 named tests
render-addons.discover corpus covered — per-file completeness asserted against the tree, no planted mutant
check-image-vulnerabilities (on #239, not this branch)

Twenty probes in scripts/tests/reverify-tests.sh, RESULT pass=20 fail=0. Each
declares the test ids that must fail, so a mutant caught by an unrelated
assertion is a MISS rather than a pass.

What was uncovered

scripts/tests/controls.py proves a gate rejects by planting the violation it
names. It cannot do that for a gate whose input arrives over a network, so
NEEDS_NETWORK_PY exempts seven. Six of those also carried no unit tests, which
left 1,107 of 3,072 statements in the gate corpus with no proof of any kind:

gate statements why it matters
check-policy-admission.py 246 decides whether any addon would be denied at admission on an Enforce cluster
check-platform-crs.py 224 the only check that the catalog's own CRs are admissible
validate-dashboards.py 224 the dashboards' only gate
render-addons.py 206 its discover() is the corpus two other gates import rather than re-derive
check-image-pins.py 109 every image reference the fleet renders
check-log-volume-budget.py 98 the Loki cutoff/alert relation

The assertion, not the number

scripts/tests/run.py gains a check with no percentage in it: every gate
controls.py exempts must carry unit coverage, with the exemption list read out
of controls.py at run time rather than copied. Three ways it could stop meaning
anything, each of which now fails:

FAIL  1 gate(s) have neither a positive control nor unit coverage:
      check-hardcoded-org.py. …
FAIL  controls.py could not be read for its control exemptions
      (AttributeError: module 'controls' has no attribute 'NEEDS_NETWORK_PY'), …
FAIL  controls.py exempts no gate from a positive control, so the assertion that
      every exempt gate carries unit tests holds over an empty set and states nothing

NOT_GATES excuses a harness on the ground that it asserts its own outcome on
every invocation — a claim about a thing something runs. Nothing ran either
harness, so that is now asserted too:

FAIL  tests/reverify-gates.sh is exempted as a harness that asserts its own
      outcome, but neither Taskfile.yaml nor a workflow under .github/workflows/
      runs it. A harness nothing invokes asserts nothing.

reverify-tests.sh runs in task validate and the gate-tests job (offline,
~11s); reverify-gates.sh gets task reverify:gates and stays off the merge
path — it runs task validate twice.

Coverage is the wrong instrument, and moves the wrong way

Gutting check_exclusion_parity raised the figure from 29.5% to 29.6%: deleting
an uncovered branch improves the ratio. The ratchet is a floor under the tests
that exist, not a check that the decisions are still made. It moves anyway —
combined 12 → 30, check-policy-admission 50 → 63, validate-dashboards 45 →
49, uncovered-gate ceiling 17 → 15 — but the planted violations above are what
the claim rests on.

Verification

All exit 0 on the branch head:

  • task validate — 25 gates (kyverno CLI at the CI pin v1.18.2)
  • ruff check .; mypy over 39 files
  • COVERAGE_REQUIRED=1 coverage run --rcfile=.coveragerc scripts/tests/run.py
    271 tests across 13 modules, 30.7% combined, all 7 control-exempt gates covered
  • ./scripts/tests/controls.py — 17 controls completed a proof
  • ./scripts/tests/reverify-tests.sh — pass=20 fail=0
  • yamllint; ./scripts/check-workflows.sh; ./scripts/check-named-things.py

Review findings, disposition

# Finding Disposition
1 dashboards verdict asserted only to be empty fixed — planted, 5 named tests
2 exclusion-parity verdict uncovered fixed — planted, 8 named tests; the misleading "asserted elsewhere" comment now names where
3 "the largest files in the tree" is false fixed — claim removed from .coveragerc and run.py; check-renovate-coverage.py (253) is larger and not exempt
5 NOT_GATES reason unchecked, nothing invokes the harnesses fixed — both invoked, and the invocation is asserted
6 discover() corpus floor is non-emptiness fixed — per-file completeness, plus per-element for matrix appsets
7 sed rationale attributed to the wrong file fixed — controls.py records it
9 NOT_GATES header says "Both" over four entries fixed
10 "all six modules" hardcoded fixed — derived from ALL_MODULES
11 test_dashboards docstring asserts history with no operand fixed — states the mechanism instead
12 security-critical-100 named without its requirement fixed — run.py records the rule as UNMET and names the gap: it asks 100%, the floor is 63
4, 8 commit-message defects in 6e3a293 and 1ab7929 left — no amend; yours at squash

One message defect of my own: d5c0ea9's body credits itself with the
reverify-tests.sh prose fixes (finding 7 and 10), which actually landed in
a8c1010 because that file was staged there. The combined squash message will be
accurate; the per-commit attribution is not.


Final round — the four minors

# Finding Disposition
1 run.py stated the approval gate floor as 50 where the table sets 63 fixed — the sentence points at the table and says why a figure written twice drifts. The consequence you named is the reason: a reader auditing the gap edits the table down to match the prose
2 CI step gave a wall-clock figure as its reason for being in the merge path fixed — the cost is stated as a property (one test module per probe, no render, no registry, no cluster). Measured 8.1s here against your 28.5s, which is itself the argument against the number
3 check_vacuity was a verdict with no planted violation fixed — see below
4 unreachable return 1 if local else 0 under the dashboard corpus floor fixed — removed

The vacuity rules now plant against themselves

You planted the violation by hand and it fired; the branch was right and held by
nobody. The rules move to vacuity_problems, which takes the lists as arguments,
so a violation is supplied rather than edited into the repository the harness is
running inside. self_test plants all four and the accepting case:

── Vacuity-rule self-test ──
  ok    a gate on no list at all
  ok    a control naming a gate that is gone
  ok    an exemption naming a harness that is gone
  ok    a harness nothing invokes
  ok    a gate covered by a control: accepted

Gutting the invocation rule fails there rather than passing:

  FAIL  a harness nothing invokes: accepted
Mutation contract FAILED its own self-test: 1 case(s).

That also closes what you named alongside it — the NOT_GATES reason for
controls.py, "self_test() runs on every invocation", covered everything except
the branch it was written beside.

Verification: task validate exit 0; ruff; mypy over 39 files;
controls.py 17 controls with the new self-test; reverify-tests.sh pass=20
fail=0.

stxkxs and others added 3 commits September 2, 2026 02:03
`scripts/tests/controls.py` proves a gate rejects by planting the violation it
names and requiring a non-zero exit. It cannot do that for a gate whose input
arrives over a network, so `NEEDS_NETWORK_PY` exempts seven. Six of those seven
also carried no unit tests, which left 1,107 of 3,072 statements in the gate
corpus with no proof of any kind — and not a random sixth of it. The set is
`check-policy-admission.py`, which decides whether any addon would be denied at
admission on an Enforce cluster; `render-addons.py`, whose `discover()` is the
corpus two other gates import rather than re-derive; `check-platform-crs.py`,
`validate-dashboards.py`, `check-image-pins.py` and `check-log-volume-budget.py`.

An exemption from one kind of proof is not an exemption from proof.

─────────────────────── The assertion, not the number ───────────────────────

`scripts/tests/run.py` gains a check that does not depend on a percentage: every
gate `controls.py` exempts must carry unit coverage. The exemption list is read
out of `controls.py` at run time rather than copied, because a second copy of an
exemption list drifts permissively — the gate added to one and not the other is
excused by both.

Three ways that check can quietly stop meaning anything, each of which now fails:

    a control-exempt gate arriving with no tests
      FAIL  1 gate(s) have neither a positive control nor unit coverage:
            check-hardcoded-org.py. controls.py exempts them because their input
            arrives over the network, so a unit test on the half that decides the
            verdict is the only proof available that they say anything at all

    the exemption list renamed out from under the reader
      FAIL  controls.py could not be read for its control exemptions
            (AttributeError: module 'controls' has no attribute
            'NEEDS_NETWORK_PY'), so no gate could be checked for having neither
            kind of proof

    the exemption list emptied
      FAIL  controls.py exempts no gate from a positive control, so the assertion
            that every exempt gate carries unit tests holds over an empty set and
            states nothing

The coverage floors move too — combined 12 to 29, the no-unit-coverage ceiling 17
to 11, and seven new per-gate floors — but they are the weaker half and the
comment in `run.py` says so. A count loose enough to survive an honest refactor
is loose enough to miss a decision going untested.

─────────────────────────── What the tests assert ───────────────────────────

157 tests across six modules, each over the decision that produces a verdict
rather than over parsing or setup. Every one of them was verified by reverting
the behaviour it names and watching the suite refuse:

  scripts/tests/test_policy_admission.py (29)
    Manifest normalisation, rule-name derivation and the two-sided verdict.
      try the shorter autogen prefix first
        FAIL: test_the_cronjob_prefix_is_stripped_whole
      keep kind-less documents in the resource file
        ERROR: test_a_kindless_document_is_dropped
      admit the runtime pod on absence of denials alone
        FAIL: test_a_pod_no_rule_evaluated_is_not_admitted
        FAIL: test_a_skip_is_neither_a_pass_nor_a_denial
        FAIL: test_a_clean_canary_cannot_carry_a_missing_runtime_pod
      count the runtime pod as a foreign addon
        FAIL: test_the_runtime_pod_is_not_counted_among_flagged_addons

  scripts/tests/test_platform_crs.py (29)
    The four rules the API server enforces and no other gate here checks:
    required-with-defaulting, pruning, declared types, list identity.
      let a bool satisfy integer, as Python does
        FAIL: test_a_bool_does_not_satisfy_integer
      read `required` without the defaulting exemption
        FAIL: test_a_missing_required_property_that_declares_a_default_is_admitted
      check list identity only at the top level
        FAIL: test_a_set_list_identifies_a_scalar_by_itself
        FAIL: test_an_absent_key_participates_in_the_identity
        FAIL: test_three_entries_sharing_an_identity_report_each_repeat

  scripts/tests/test_dashboards.py (28)
    The offline extractors: variable references in all four Grafana spellings,
    the `json: |` block, nested panels, and which datasources count as wired.
      match only the ${name} variable form
        FAIL: test_the_bare_form_every_dashboard_here_uses
        FAIL: test_the_bracket_form
        FAIL: test_a_builtin_beside_a_real_variable_leaves_the_real_one
      scan panels flat, without descending into a collapsed row
        FAIL: test_an_alert_inside_a_collapsed_row_is_found
        FAIL: test_a_top_level_alert_panel_is_found
        FAIL: test_an_untitled_alert_panel_is_still_reported
      glob the datasource directory instead of reading the kustomization
        FAIL: test_a_datasource_file_absent_from_resources_is_not_wired

  scripts/tests/test_render_addons.py (29)
    Unit discovery and the exit-code classification that separates a pin which
    does not resolve from a registry that could not be reached.
      call any missing-chart message a finding about this repo
        FAIL: test_a_message_naming_both_is_read_as_unreachable
      append the chart name to every OCI repoURL
        FAIL: test_a_repo_url_ending_in_the_chart_name_is_used_as_is
      take the addon path from any values file
        FAIL: test_a_per_environment_file_alone_does_not_supply_the_path

  scripts/tests/test_image_pins.py (23)
    Reference classification and both directions of the exemption check.
      look for the tag colon anywhere in the reference
        FAIL: test_a_registry_port_is_not_read_as_a_tag
      stop re-checking exemptions against the render
        FAIL: test_an_exemption_the_fleet_no_longer_renders_mutably_fails
        FAIL: test_an_exemption_for_an_image_now_pinned_by_tag_fails
        ERROR: test_the_recorded_reason_is_quoted_back

  scripts/tests/test_log_volume_budget.py (19)
    The relation the gate exists for — the fill alert leads the ingestion cutoff
    — plus every way the alert can stop supplying its operand.
      let the alert fire at the cutoff rather than before it
        FAIL: test_a_warning_at_the_cutoff_leaves_no_window
      accept a rule keyed on the edge counter
        FAIL: test_a_rule_querying_the_edge_counter_fails_twice
        FAIL: test_a_rule_querying_both_still_fails_on_the_edge_counter

Bytecode caching is disabled while a mutant is under test. It keys on mtime and
size, so a restore and a re-mutation inside the same second can hand the next run
the previous mutant's module — which reads as the suite catching a mutant it
never saw.

──────────────────────── Three verdicts made reachable ────────────────────────

Three gates computed their verdict inline with the network call that fed it, so
the decision could only be exercised through a round trip. Each is extracted
whole, with no change to what it decides or to what it prints:

  scripts/check-log-volume-budget.py  `environment_verdict(cfg, warn, rel)`
      returns the problems found and whether the alert leads a declared cutoff.
      The second value is what the closing line counts, so an environment that
      failed the comparison is not also reported as one the comparison covered.

  scripts/check-image-pins.py         `verdict(images, allowed)`, `bare_name(ref)`
      `bare_name` splits on the last colon only when it sits in the final path
      segment, so a registry port is not read as a tag.

  scripts/render-addons.py            `registry_answered(err)`
      true when helm's complaint says the registry replied and refused the pin.
      A message naming both a missing chart and a broken connection is not one:
      an unreachable registry cannot testify about what it holds.

The summary lines these gates print are unchanged — 55 rendered images across 26
charts, four Loki environments checked against an alert at 0.75.

────────────────────────────── Why not a number ──────────────────────────────

Raising the coverage floor alone would have left the same hole. The floor is a
ratchet over the whole corpus, so a gate arriving with no tests dilutes it by a
percentage point and passes; and the six gates in question were the largest files
in the tree, so the number they were absent from was the number they dominated.
`.coveragerc` said as much and the figure stayed low anyway. What closes it is a
per-gate property with the exemption list as its operand.

Co-authored-by: stxkxsbot <275011021+stxkxsbot@users.noreply.github.com>
The previous commit's mutation results were produced out of tree, so the note
about bytecode caching named a procedure a reader cannot run and the seventeen
probes existed nowhere. A proof nobody can re-run is the shape this repo rejects
everywhere else.

`scripts/tests/reverify-tests.sh` is that procedure, as a sibling to
`scripts/tests/reverify-gates.sh`. The existing harness proves a GATE rejects a
planted defect; this proves the TESTS reject a reverted behaviour, which a
passing suite cannot establish on its own — a test that asserts what it just
constructed passes forever, and so does one whose subject was rewritten
underneath it.

─────────────────────────── Naming, not just failing ───────────────────────────

Each probe declares the test ids that must fail, and a run that goes red without
them is reported as a MISS rather than a pass:

    MISS  classify: find the tag colon anywhere in the reference   rejected, but
          not by test_a_version_tag_is_accepted
    RESULT pass=16 fail=1

A non-zero exit alone proves the suite noticed something, not that the assertion
which noticed is the one describing the behaviour. A mutant caught through an
unrelated fixture has demonstrated detection without demonstrating coverage, and
the two are indistinguishable from an exit code.

The other two ways it can stop meaning anything fail as well:

    MISS  alert: accept a rule keyed on the edge counter           the suite
          passed the mutant
    RESULT pass=16 fail=1

    RESULT pass=4 fail=0
    FAIL  ran 4 probe(s), under the floor of 17 — this harness
          planted almost nothing, which is not the same as every test holding.

──────────────────────────────── What it plants ────────────────────────────────

Seventeen probes across the six modules, asserting the clean tree is green before
anything is planted and green again after. On the tree as it stands:

    ── Clean tree: the suite must PASS before anything is planted ──
      ok    all six modules green on the unmodified tree

    ── One behaviour reverted at a time; the suite must name it ──
      ok    autogen: strip the shorter prefix first
              FAIL: test_the_cronjob_prefix_is_stripped_whole
      ok    prepare: keep kind-less documents
              ERROR: test_a_kindless_document_is_dropped
      ok    runtime pod: admit on absence of denials alone
              FAIL: test_a_pod_no_rule_evaluated_is_not_admitted
              FAIL: test_a_skip_is_neither_a_pass_nor_a_denial
              FAIL: test_a_clean_canary_cannot_carry_a_missing_runtime_pod
      ok    judge: count the runtime pod as a foreign addon
              FAIL: test_the_runtime_pod_is_not_counted_among_flagged_addons
      ok    types: let a bool satisfy integer, as Python does
              FAIL: test_a_bool_does_not_satisfy_integer
      ok    required: drop the defaulting exemption
              FAIL: test_a_missing_required_property_that_declares_a_default_is_admitted
      ok    list identity: check only the top level
              FAIL: test_a_set_list_identifies_a_scalar_by_itself
              FAIL: test_an_absent_key_participates_in_the_identity
              FAIL: test_three_entries_sharing_an_identity_report_each_repeat
      ok    variables: match only the braced form
              FAIL: test_the_bare_form_every_dashboard_here_uses
              FAIL: test_the_bracket_form
              FAIL: test_a_builtin_beside_a_real_variable_leaves_the_real_one
      ok    alerts: scan panels flat, skipping collapsed rows
              FAIL: test_an_alert_inside_a_collapsed_row_is_found
              FAIL: test_a_top_level_alert_panel_is_found
              FAIL: test_an_untitled_alert_panel_is_still_reported
      ok    datasources: glob the directory, not the kustomization
              FAIL: test_a_datasource_file_absent_from_resources_is_not_wired
      ok    helm failure: call every missing-chart message a finding
              FAIL: test_a_message_naming_both_is_read_as_unreachable
      ok    oci: append the chart name to every repoURL
              FAIL: test_a_repo_url_ending_in_the_chart_name_is_used_as_is
      ok    addon path: take it from any values file
              FAIL: test_a_per_environment_file_alone_does_not_supply_the_path
      ok    classify: find the tag colon anywhere in the reference
              FAIL: test_a_registry_port_is_not_read_as_a_tag
      ok    exemptions: stop re-checking them against the render
              FAIL: test_an_exemption_the_fleet_no_longer_renders_mutably_fails
              FAIL: test_an_exemption_for_an_image_now_pinned_by_tag_fails
      ok    cutoff: let the alert fire AT it rather than before
              FAIL: test_a_warning_at_the_cutoff_leaves_no_window
      ok    alert: accept a rule keyed on the edge counter
              FAIL: test_a_rule_querying_the_edge_counter_fails_twice
              FAIL: test_a_rule_querying_both_still_fails_on_the_edge_counter

    ── Restored tree must be green again ──
      ok    all six modules green again

    RESULT pass=17 fail=0

──────────────────────────── Two properties it needs ────────────────────────────

Bytecode is cleared and disabled around every probe. The cache keys on mtime and
size, so a restore and the next mutation inside the same second can hand the run
the previous mutant's module — and the suite then reports the previous mutant's
failing test against this mutant's label. That is a green line naming the wrong
assertion, which is worse than a red one, and the naming requirement above is
what surfaces it.

Backups live outside the scratch directory the cleanup removes, and restoration
runs on INT and TERM as well as EXIT. The probes plant defects in tracked gate
scripts; between planting and restoring the backup is the only copy of the
original, and `scripts/tests/reverify-gates.sh` records what happens when that
copy sits inside the directory the teardown deletes.

Co-authored-by: stxkxsbot <275011021+stxkxsbot@users.noreply.github.com>
`scripts/tests/controls.py` enumerates every executable under `scripts/` and
requires each to carry either a positive control or an entry saying why it cannot.
Adding `scripts/tests/reverify-tests.sh` without one failed that check before it
ran anything:

    FAIL  tests/reverify-tests.sh ships no positive control and is on no
          exemption list. A gate nobody has shown to fail is an untested
          assertion about the tree.

The exemption is the right answer here rather than a control, for the reason
`NOT_GATES` already records for its two neighbours: a harness that drives the
gates is not itself checking the tree, and a control over it would be the thing
under test and the thing testing it at once. What stands in for one is its own
self-assertion on every invocation — the clean-tree and restored-tree checks, the
requirement that each mutant be named by the assertion describing it, and the
probe floor.

The entry is asserted in both directions, like every other exemption here.
Renaming the file fails on both sides at once:

    FAIL  tests/reverify-tests.sh is exempted as a harness rather than a gate,
          but no such executable exists under scripts/ — the exemption outlived
          its file.
    FAIL  tests/reverify-tests-renamed.sh ships no positive control and is on no
          exemption list.

Co-authored-by: stxkxsbot <275011021+stxkxsbot@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

CI Results

Check Status
Zero-placeholder gate ✅ success
YAML Lint ✅ success
Dashboard gate (live grafana.com ids + AMG-saveable) ✅ success
Kyverno policy tests (+ verify-images contract) ✅ success
Fork-safety gate (no hardcoded org, blocking) ✅ success
Helm-render (every addon × every env) ✅ success
Policy-admission (Enforce-tier Kyverno vs the fleet) ✅ success
ApplicationSet schema + sync waves ✅ success
Appset render (Karpenter subnet selector) ✅ success
Secret scan (gitleaks) ✅ success
Render + assert + schema + misconfig (all environments) ✅ success
Renovate manager coverage ✅ success
Loki volume warns before cutoff ✅ success
Falco loads every rule set it installs ✅ success
Gate scripts lint and typecheck ✅ success
Policy validity (kustomize + kyverno) ✅ success
The gates themselves are tested ✅ success
Pods name ServiceAccounts that exist ✅ success
Catalog CRs admissible against the operator chart ✅ success
Catalog source reads its revision ✅ success

All checks passed.

stxkxs and others added 2 commits September 2, 2026 03:49
Two verdicts decided the exit code of a control-exempt gate and were asserted
only to be empty on a healthy tree. That claim is satisfied by every
implementation that reports nothing, `return []` included, so it is a control
against false positives rather than evidence of detection.

`check_local_dashboards` is the whole offline half of validate-dashboards: an
unwired panel datasource, an undeclared template variable, a locally-authored
board whose JSON cannot be read, and a floor that fires when the corpus declares
variables and references none. Each is now planted against a fixture tree and the
message it produces is named. Replacing the function body with `return []` is
killed by five tests.

`check_exclusion_parity` is the offline half of check-policy-admission, and a
divergence between the four exclusion lists is invisible to every other gate —
each policy is individually valid, renders, and passes kyverno's unit tests. It
surfaces on a vended Enforce cluster as one workload denied where its three
siblings were admitted. A divergent list, an extra namespace, a reordering that
is not a divergence, and a second `exclude.any` entry are now planted; returning
True unconditionally is killed by seven tests, and reading only `any[0]` by one.

The harness gains three probes so its naming requirement reaches the decisions
rather than the extractors beneath them:

    ok    offline verdict: report nothing, whatever the tree holds
            FAIL: test_a_panel_naming_an_unwired_datasource_is_reported
            FAIL: test_an_undeclared_template_variable_is_reported
            FAIL: test_a_locally_authored_board_whose_json_cannot_be_read_is_reported
            FAIL: test_a_declared_variable_nothing_references_reports_a_broken_parser
            FAIL: test_every_detection_is_reported_from_one_pass
    ok    parity verdict: agree, whatever the four policies hold
            FAIL: test_four_identical_lists_agree
            FAIL: test_one_list_missing_a_namespace_is_a_mismatch
            FAIL: test_one_list_carrying_an_extra_namespace_is_a_mismatch
            FAIL: test_the_namespaces_returned_are_the_shared_baseline
            FAIL: test_the_shipped_policies_agree
    ok    parity: read only the first exclude.any entry
            FAIL: test_the_union_of_both_entries_is_the_list

    RESULT pass=20 fail=0

Coverage is not the instrument for any of this and moves the wrong way when a
verdict is emptied: deleting an uncovered branch raises the ratio. The floors
ratchet anyway — combined 29 to 30, check-policy-admission 50 to 63,
validate-dashboards 45 to 49 — and run.py now records that
`security-critical-100` asks for a per-file 100% override on the approval gate
and that its floor sits at 63, so the rule is named with its requirement rather
than as though citing it satisfied it.

Co-authored-by: stxkxsbot <275011021+stxkxsbot@users.noreply.github.com>
`NOT_GATES` excuses a file from carrying a positive control on the ground that it
asserts its own outcome on every ordinary invocation. That is a claim about a
thing something runs. Neither `Taskfile.yaml` nor any workflow ran either
re-verification harness, so the exemption covered two executables that never
executed and its recorded reason was free text nothing read.

`check_vacuity` now fails an entry the Taskfile and the workflows do not name:

    FAIL  tests/reverify-gates.sh is exempted as a harness that asserts its own
          outcome, but neither Taskfile.yaml nor a workflow under
          .github/workflows/ runs it. A harness nothing invokes asserts nothing.

`scripts/tests/reverify-tests.sh` runs in `task validate` and in the `gate-tests`
job — offline, about eleven seconds. `scripts/tests/reverify-gates.sh` gets
`task reverify:gates` and stays out of the merge path: it runs `task validate`
twice and plants defects against gitleaks and trivy.

The corpus assertion on `discover()` was non-emptiness, which one unit satisfies
while the omission that walk produces is partial. It is now per file: every
ApplicationSet pinning a Helm chart must contribute a unit, and every matrix
element pinning one must appear among that appset's units. Three gates read this
corpus, and all three derive their printed counts from it.

Two prose corrections. `.coveragerc` and `run.py` claimed the control-exempt
gates are the largest files in the tree; `check-renovate-coverage.py` at 253
statements is larger than every one of them and is not exempt, so the claim is
gone rather than restated. `reverify-tests.sh` attributed the sed-portability
rationale to `reverify-gates.sh`, which does not record it — `controls.py` does.
The harness also prints its module count from `ALL_MODULES` instead of the
literal six.

Co-authored-by: stxkxsbot <275011021+stxkxsbot@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

CI Results

Check Status
Zero-placeholder gate ✅ success
YAML Lint ✅ success
Dashboard gate (live grafana.com ids + AMG-saveable) ✅ success
Kyverno policy tests (+ verify-images contract) ✅ success
Fork-safety gate (no hardcoded org, blocking) ✅ success
Helm-render (every addon × every env) ✅ success
Policy-admission (Enforce-tier Kyverno vs the fleet) ✅ success
ApplicationSet schema + sync waves ✅ success
Appset render (Karpenter subnet selector) ✅ success
Secret scan (gitleaks) ✅ success
Render + assert + schema + misconfig (all environments) ✅ success
Renovate manager coverage ✅ success
Loki volume warns before cutoff ✅ success
Falco loads every rule set it installs ✅ success
Gate scripts lint and typecheck ✅ success
Policy validity (kustomize + kyverno) ✅ success
The gates themselves are tested ✅ success
Pods name ServiceAccounts that exist ✅ success
Catalog CRs admissible against the operator chart ✅ success
Catalog source reads its revision ✅ success

All checks passed.

`check_vacuity` decides controls.py's exit code and nothing exercised it. Its
list rules are the ones the rest of this file's claim rests on — a gate on no
list, a control naming a gate that is gone, an exemption for a harness nothing
runs — and each was correct and asserted by nobody. That is the shape one level
down from the one the harness-invocation rule was added to reject.

The rules move to `vacuity_problems`, which takes the lists as arguments, so a
violation is planted by supplying them rather than by editing the repository the
harness is running inside. `self_test` plants all four and the accepting case:

    ── Vacuity-rule self-test ──
      ok    a gate on no list at all: check-x.py ships no positive control and is…
      ok    a control naming a gate that is gone: check-x.py is named by a control…
      ok    an exemption naming a harness that is gone: tests/gone.py is exempted…
      ok    a harness nothing invokes: tests/gone.py is exempted as a harness that…
      ok    a gate covered by a control: accepted

Gutting the invocation rule now fails there rather than passing:

      FAIL  a harness nothing invokes: accepted
    Mutation contract FAILED its own self-test: 1 case(s).

Three repairs alongside it.

`run.py` stated the approval gate's floor as 50 where the table sets 63 — the
prose whose job is to keep `security-critical-100` from reading as satisfied
misreported the number it cites, and a reader auditing the gap would edit the
table down to match and unratchet the gate. The sentence now points at the table
and says why a figure written twice drifts.

The CI step gave a wall-clock figure as the reason for putting the harness in the
merge path. A measurement stated as documentation goes stale on the next probe
and on any machine but the one it was taken on; the step states its cost as a
property instead — one test module per probe, no render, no registry, no cluster.

`validate-dashboards.py` carried `return 1 if local else 0` directly after an
unconditional `return 2` inside the same block, reading as a second, softer exit
path the gate does not have.

Co-authored-by: stxkxsbot <275011021+stxkxsbot@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

CI Results

Check Status
Zero-placeholder gate ✅ success
YAML Lint ✅ success
Dashboard gate (live grafana.com ids + AMG-saveable) ✅ success
Kyverno policy tests (+ verify-images contract) ✅ success
Fork-safety gate (no hardcoded org, blocking) ✅ success
Helm-render (every addon × every env) ✅ success
Policy-admission (Enforce-tier Kyverno vs the fleet) ✅ success
ApplicationSet schema + sync waves ✅ success
Appset render (Karpenter subnet selector) ✅ success
Secret scan (gitleaks) ✅ success
Render + assert + schema + misconfig (all environments) ✅ success
Renovate manager coverage ✅ success
Loki volume warns before cutoff ✅ success
Falco loads every rule set it installs ✅ success
Gate scripts lint and typecheck ✅ success
Policy validity (kustomize + kyverno) ✅ success
The gates themselves are tested ✅ success
Pods name ServiceAccounts that exist ✅ success
Catalog CRs admissible against the operator chart ✅ success
Catalog source reads its revision ✅ success

All checks passed.

A harness exempted from carrying a positive control excuses itself by
asserting its own outcome whenever it runs, so the exemption is worth
what "whenever it runs" is worth. The reader holding that half searched
the raw bytes of Taskfile.yaml and the workflows for the harness's path,
which a comment naming the harness satisfies — and .github/workflows/ci.yml
carries two such comments about scripts/tests/controls.py.

─── The reader ───

`invoked_anywhere` now asks the callers what they execute. Each caller is
parsed, the commands are taken from the positions a runner takes them from
— a task's `cmds:` entries, a workflow step's `run:` script — and each
command is split into the words it would run, shell comments blanked and
quoting resolved. A YAML comment is not in the parse; a `desc:`, a step
`name:` and a quoted mention inside a command are not commands.

`status:` and `preconditions:` are left out and the reason is recorded:
they decide whether a task's work runs, so a harness reached only through
one asserts nothing.

Two limits are stated in the function, both toward reporting a harness as
un-invoked rather than as invoked: a path assembled at run time from a
variable is not resolved, and a word found in a command is not proved to
be that command's executable. What the reader separates is prose from
command text.

A caller that will not parse is now its own finding. It and a caller that
runs nothing are the same value to `any()` and different facts to whoever
has to fix one, and the first used to print as four stale exemptions.

─── The proof ───

scripts/tests/test_controls.py plants a violation against the reader
rather than against a stub standing in for it: seven callers that name the
harness and do not run it, five that run it, and both directions of the
unparseable case. Two more assert the rule reaches the reader by default —
one harness this repo runs, one it does not — because a reader returning a
constant passes either alone.

scripts/tests/reverify-tests.sh reverts seven of those behaviours one at a
time and requires the test that describes each to be the test that names
it. Its floor moves to 27 and test_controls joins the modules it asserts
green before and after.

The quoted-mention fixture puts the path mid-string. At the end of one the
closing quote stays attached under any splitter that ignores quoting, and
the case is then answered correctly by a reader that cannot read quoting
at all.

Co-authored-by: stxkxsbot <275011021+stxkxsbot@users.noreply.github.com>
@stxkxs

stxkxs commented Sep 2, 2026

Copy link
Copy Markdown
Member Author

The invocation reader is now behavioural, and it is asserted by planted violations rather than by a stub.

What the reader does. invoked_anywhere asks the callers what they execute. Each caller is parsed; commands come from the positions a runner takes them from — a task's cmds: entries, a workflow step's run: script — and each command is split into the words it would run, with shell comments blanked and quoting resolved. A YAML comment is not in the parse at all; a desc:, a step name: and a quoted mention inside a command are not commands.

Proof on the real tree, both directions. The two comments in .github/workflows/ci.yml naming scripts/tests/controls.py are already there — no planting needed. Remove only the two commands that actually run it (Taskfile.yaml cmds: and the ci.yml run: step), leaving those comments:

pre-branch reader:  invoked_anywhere('tests/controls.py') = True
                    check_vacuity() = []                        exit 0

this reader:        ── Control coverage ──
                      FAIL  tests/controls.py is exempted as a harness that
                      asserts its own outcome, but neither Taskfile.yaml nor a
                      workflow under .github/workflows/ runs it. A harness
                      nothing invokes asserts nothing.
                    Positive-control gate FAILED before running anything.   exit 1

Proof of the reader itself. scripts/tests/test_controls.py, 16 tests: seven callers that name the harness and do not run it, five that run it, both directions of the unparseable case, and two that assert the rule reaches the reader by default — one harness this repo runs, one it does not — because a reader returning a constant passes either of those alone.

Seven probes in scripts/tests/reverify-tests.sh, each named by the test that describes the behaviour:

ok  invocation: answer yes for any name at all
      FAIL: test_a_yaml_comment_in_the_taskfile_does_not_count
      FAIL: test_a_task_description_does_not_count
      FAIL: test_a_step_name_does_not_count
      FAIL: test_a_harness_this_repo_does_not_run_is_reported
ok  invocation: search the caller's text, not its commands
      FAIL: test_a_yaml_comment_in_the_taskfile_does_not_count
      FAIL: test_a_task_description_does_not_count
      FAIL: test_a_step_name_does_not_count
      FAIL: test_a_shell_comment_inside_a_run_block_does_not_count
      FAIL: test_a_quoted_mention_inside_a_command_does_not_count
ok  callers: read the Taskfile's commands and no workflow's
      FAIL: test_a_workflow_run_step_counts
      FAIL: test_a_command_below_a_comment_naming_it_still_counts
ok  words: read a run block's shell comments as command text
      FAIL: test_a_shell_comment_inside_a_run_block_does_not_count
ok  words: split on whitespace, ignoring quoting
      FAIL: test_a_quoted_mention_inside_a_command_does_not_count
ok  callers: read an unparseable caller as one running nothing
      FAIL: test_the_unparseable_caller_is_named
ok  rule: reach a constant instead of the reader
      FAIL: test_a_harness_this_repo_does_not_run_is_reported

RESULT pass=27 fail=0

One fixture was fixed by its own probe. The quoting probe first came back MISS — the suite passed the mutant: the fixture put the path at the end of a quoted string, where the closing quote stays attached to the token under any splitter that ignores quoting, so a whitespace-splitting reader answered it correctly for a reason unrelated to quoting. The mention now sits mid-string and the probe kills the mutant.

Stated limits, in the function. Both point toward reporting a harness as un-invoked rather than as invoked: a path assembled at run time from a variable is not resolved, and a word found in a command is not proved to be that command's executable — what the reader separates is prose from command text, not one word of a command from another. status: and preconditions: are excluded with the reason recorded: they decide whether a task's work runs.

Gates: ruff clean, mypy clean over 40 files, run.py 287 tests across 14 modules with the ratchet at 30.7% (floor 30), ./scripts/tests/controls.py 17 controls all proving, reverify-tests.sh 27/27, task validate exit 0.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

CI Results

Check Status
Zero-placeholder gate ✅ success
YAML Lint ✅ success
Dashboard gate (live grafana.com ids + AMG-saveable) ✅ success
Kyverno policy tests (+ verify-images contract) ✅ success
Fork-safety gate (no hardcoded org, blocking) ✅ success
Helm-render (every addon × every env) ✅ success
Policy-admission (Enforce-tier Kyverno vs the fleet) ✅ success
ApplicationSet schema + sync waves ✅ success
Appset render (Karpenter subnet selector) ✅ success
Secret scan (gitleaks) ✅ success
Render + assert + schema + misconfig (all environments) ✅ success
Renovate manager coverage ✅ success
Loki volume warns before cutoff ✅ success
Falco loads every rule set it installs ✅ success
Gate scripts lint and typecheck ✅ success
Policy validity (kustomize + kyverno) ✅ success
The gates themselves are tested ✅ success
Pods name ServiceAccounts that exist ✅ success
Catalog CRs admissible against the operator chart ✅ success
Catalog source reads its revision ✅ success

All checks passed.

#241 landed the vacuity harness, GATE_ARGS, gatelib.read_yaml across four
gates, and corpus floors on check-platform-crs, check-policy-admission,
validate-dashboards and kyverno-test.sh. This branch plants violations
against those same offline verdicts and asserts the control-exempt gates,
so the two work the same ground from opposite directions.

Four textual conflicts, all of them both-sides-added rather than
either-side-changed. Each is resolved by keeping both, in one order that
the Taskfile and the workflow now share:

  .github/workflows/ci.yml — both branches inserted a step after the
  positive controls. `empty-corpus.py` asserts a GATE rejects an absent
  corpus and `reverify-tests.sh` asserts the TESTS reject a reverted
  behaviour, so the gate-level probe runs beside the other gate-level ones
  and the suite-level one after them.

  Taskfile.yaml, twice — the target definitions and the `validate` list,
  ordered to match the workflow so reading either gives the same sequence.

  scripts/tests/controls.py — both added a NOT_GATES entry. Both harnesses
  are exempt for the same reason and both keep their recorded reason.

  scripts/tests/run.py — both added to EXPECTED. `test_corpus_floors` joins
  the harness layer with a line saying what it holds. The comment above
  `test_controls` counted the exempt harnesses; it now states the rule
  instead, because the count was about to be wrong and would have stayed
  readable while being false.

──────────────── What the merge changed beyond the conflicts ────────────────

`empty-corpus.py` is a harness registered in NOT_GATES, so it enters the
population of this branch's newest rule: a harness exempted for
self-assertion must be invoked. It is — by `validate:empty-corpus` and by
its own CI step — and the rule reaches it. Removing both commands while
leaving the task named after it makes `invoked_anywhere` answer False and
`check_vacuity` name the file with its recorded reason, so the coverage is
real rather than incidental.

`check-platform-crs.py` gained a `Cannot run` refusal when the operator
ApplicationSet is absent, and its per-gate coverage floor read 49% against a
floor of 50 — a floor doing exactly what a ratchet is for. Resolved by
covering the verdict rather than lowering the number:
`TheVersionThePinResolves` holds the four things `pinned_chart_version`
decides, since the version it reads is upstream of every schema assertion in
that module. Four probes in `reverify-tests.sh`, floor 27 → 31, each killed
and named. Coverage 52%, floors raised to 51 and 31.

`reverify-tests.sh` re-runs `test_corpus_floors` too. The floors #241 added
sit in three gates this harness already mutates against, so a mutant
reverting the floor half is held by that module and by nothing else in the
list — without it, a caught mutant read as a miss. Its "all N modules green"
line now says these are the modules the harness mutates against, which is
what N was always counting.

──────────────── Verification on the merged tree ────────────────

ruff clean; mypy clean over 42 files; 297 tests across 15 modules; coverage
ratchet 31.5% combined (floor 30 → 31), 12 per-gate floors held, 10 of 23
gates with no unit coverage against a ceiling of 11; controls.py 17 controls
each rejecting at exit 1 naming the mutated file, so no planted violation
trips a new floor first; empty-corpus.py 28 probed gates; reverify-tests.sh
31/31; task validate exit 0; check-named-things.py 187 references resolve;
check-workflows.sh clean at MEDIUM and above; renovate-config-validator
accepts the config.

Co-authored-by: stxkxsbot <275011021+stxkxsbot@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

CI Results

Check Status
Zero-placeholder gate ✅ success
YAML Lint ✅ success
Dashboard gate (live grafana.com ids + AMG-saveable) ✅ success
Kyverno policy tests (+ verify-images contract) ✅ success
Fork-safety gate (no hardcoded org, blocking) ✅ success
Helm-render (every addon × every env) ✅ success
Policy-admission (Enforce-tier Kyverno vs the fleet) ✅ success
ApplicationSet schema + sync waves ✅ success
Appset render (Karpenter subnet selector) ✅ success
Secret scan (gitleaks) ✅ success
Render + assert + schema + misconfig (all environments) ✅ success
Renovate manager coverage ✅ success
Loki volume warns before cutoff ✅ success
Falco loads every rule set it installs ✅ success
Gate scripts lint and typecheck ✅ success
Policy validity (kustomize + kyverno) ✅ success
The gates themselves are tested ✅ success
Pods name ServiceAccounts that exist ✅ success
Catalog CRs admissible against the operator chart ✅ success
Catalog source reads its revision ✅ success

All checks passed.

One conflict, in scripts/tests/run.py. Both sides changed the paragraph
above COMBINED_FLOOR: main's states that the control-exempt gates have
neither unit nor behavioural coverage, which is what this branch's tests
made false. This branch's paragraph and its `control_exempt_gates` check —
which reads the exemption list out of controls.py and fails on any gate in
both it and the uncovered set — are what hold on the merged tree, so they
stand.

The floor itself is measured on the merge rather than taken from either
side: 37, against a reading of 37.5%.

#240's changes come in cleanly. `.node-version`, the nodenv manager, the
reach assertion at every certification site, and the Renovate defaults
record touch none of the files this branch changed.

Verification on the merged tree: ruff clean; mypy clean over 43 files; 386
tests across 16 modules; coverage ratchet 37.5% (floor 31 → 37), 12 per-gate
floors held, 10 of 23 gates with no unit coverage against a ceiling of 11,
and all 7 control-exempt gates carrying unit coverage; controls.py 17
controls each rejecting at exit 1 naming the mutated file; empty-corpus.py
28 probed gates; reverify-tests.sh 31/31; reverify-gates.sh 35/35; task
validate exit 0; check-named-things.py 191 references resolve;
check-workflows.sh clean at MEDIUM and above; check-renovate-coverage.py and
check-renovate-defaults.mjs both exit 0; renovate-config-validator accepts
the config.

Co-authored-by: stxkxsbot <275011021+stxkxsbot@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown

CI Results

Check Status
Zero-placeholder gate ✅ success
YAML Lint ✅ success
Dashboard gate (live grafana.com ids + AMG-saveable) ✅ success
Kyverno policy tests (+ verify-images contract) ✅ success
Fork-safety gate (no hardcoded org, blocking) ✅ success
Helm-render (every addon × every env) ✅ success
Policy-admission (Enforce-tier Kyverno vs the fleet) ✅ success
ApplicationSet schema + sync waves ✅ success
Appset render (Karpenter subnet selector) ✅ success
Secret scan (gitleaks) ✅ success
Render + assert + schema + misconfig (all environments) ✅ success
Renovate manager coverage ✅ success
Loki volume warns before cutoff ✅ success
Falco loads every rule set it installs ✅ success
Gate scripts lint and typecheck ✅ success
Policy validity (kustomize + kyverno) ✅ success
The gates themselves are tested ✅ success
Pods name ServiceAccounts that exist ✅ success
Catalog CRs admissible against the operator chart ✅ success
Catalog source reads its revision ✅ success

All checks passed.

@stxkxs
stxkxs marked this pull request as ready for review September 5, 2026 00:59
@stxkxs
stxkxs merged commit 7d958f6 into main Sep 5, 2026
30 checks passed
@stxkxs
stxkxs deleted the prove-the-control-exempt-gates branch September 5, 2026 00:59
stxkxs added a commit that referenced this pull request Sep 5, 2026
#238 landed controls.py's vacuity rules taking their lists as arguments,
run.py's control-exempt coverage check, the per-file corpus assertion on
discover(), and reverify-tests.sh in task validate. This branch reads the
image population out of that same discover(), so the two meet there.

──────────────── scripts/check-image-pins.py ────────────────

Two hunks, both from #238 extracting the mutable-tag verdict out of main()
into a testable `verdict(images, allowed)` and bringing a `bare_name` with
it.

The extraction is kept — it is what the tests #238 added call. The
`bare_name` that came with it is dropped as a duplicate: this branch's
strips the digest before looking for a tag, and #238's does not, so it would
key `ghcr.io/x/y@sha256:<hex>` as `ghcr.io/x/y@sha256` and no exemption
would match it. One reader, and it is the one that reads both forms.

`verdict()` uses this branch's MUTABLE_REMEDIATION rather than the sentence
it was extracted with, because a test reads the reference forms out of that
constant and checks the pattern reads each one. A message retyped inside the
function would drift from the pattern with nothing to notice.

main() keeps this branch's shape — the per-chart floor, and the split
between a chart that did not render and a reference that could not be placed
— and calls verdict() for the mutable half.

──────────────── scripts/tests/run.py ────────────────

Four hunks. EXPECTED and PER_GATE_FLOORS are unions: both sides added
entries, and both name check-image-pins.py, whose floor is measured on the
merged tree that carries both sides' tests for it — 88 against a reading of
89%.

COMBINED_FLOOR was raised from one base by both sides. A ratchet is measured,
not chosen: 40, against 40.8%.

MAX_UNCOVERED_GATES ratchets DOWNWARD, so the lower of the two holds: 11.
This branch's paragraph stays with it, because what it records is still
true — two of the files counted as covered are covered by IMPORT rather than
by tests, since check-image-vulnerabilities.py loads check-image-pins.py by
path and that loads render-addons.py in turn.

──────────────── One corpus, confirmed rather than assumed ────────────────

#238's per-file assertion requires every ApplicationSet pinning a chart to
contribute a unit and every matrix element pinning one to appear among that
appset's units. `inventory` walks exactly those units, and `chart_coverage`
then requires each to have contributed an image. Passing over a reference
helm reported pulling sits between the two.

It cannot take a real contribution: a chart artifact is not an image the
chart deploys and never entered the population. What it must not do is leave
a chart looking covered while contributing nothing, and that is asserted
rather than argued — a chart whose render carries only its own pulled
coordinate contributes no image and the per-chart floor names it.

Measured on the tree under the stream shape that engages the reader — helm's
pull report on stdout, cold OCI cache: 32 units discovered, 28 contributing,
no chart named by the inventory that discover() does not have, and
chart_coverage empty. The reverify probe holds that shape durably.

──────────────── Verification on the merged tree ────────────────

ruff clean; mypy clean over 46 files; 476 tests across 18 modules; coverage
ratchet 40.8% (floor 37 → 40), 13 per-gate floors held, 10 of 24 gates with
no unit coverage against a ceiling of 11, and all 8 control-exempt gates
carrying unit coverage; controls.py 17 controls; empty-corpus.py 29 probed
gates; reverify-tests.sh 31/31; reverify-gates.sh 38/38; task validate exit
0; check-named-things.py 195 references resolve; check-workflows.sh clean at
MEDIUM and above.

Co-authored-by: stxkxsbot <275011021+stxkxsbot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants