Skip to content

[EPIC] Make this repository's guards actually run (cluster G / C-70) #66

Description

@Polichinel

Make this repository's guards actually run

The problem

/review-rr prioritize (2026-08-09) returned CLEAR PRIORITY: cluster G — "Guards that are green and blind." Seven concerns, one root cause: a check is written to confirm a state, never to detect its absence.

Six of the seven are already fixed — C-52 (a guard pointing at a path that did not exist, so it graded two byte-identical clones), C-53 (a version check that passed when neither side moved), C-55 (a guard that skipped itself into dormancy), C-67 (a secret scan that missed both leak shapes this platform has actually leaked), C-68 (a stub that went green without its finding being resolved). C-62 is views-models' (views-models#330).

What remains is the systemic hole, and it got worse on 2026-08-08. This repo acquired its first CI workflow — a full-history secret scan — and the new ruleset made it a required check. That workflow runs none of the guards:

Guard Protects Runs in CI?
tests/test_registry_reader_contract.py (5 tests) the C-29 invariant; no secret carries a value no
tests/test_registry_readers_agree.py (6 tests) the three canonical readers still agree no
docs/validate_docs.sh (8 checks) contract/registry version lockstep; no silent drift no
.github/workflows/secret_scan.yml no credentials in git history yes

Why it matters

Commit 2186d45 — which put four value-less slots in [target] and made the coordinate registry unreadable platform-wide for a day (C-29) — would merge with a green tick today.

The guard written afterwards catches it, but only if a human remembers to run pytest locally first. Under the new ruleset the required status check is the secret scan.

Until 2026-08-08 nobody could believe this repository was mechanically covered; it visibly had no workflows. It now has a green tick on every PR that verifies nothing about the registry. The appearance of coverage arrived without the coverage. That is cluster G, one level up, and it is why this is Tier 2 rather than Tier 3.

Investigation findings that shape the design

All measured, not assumed. Recorded here because each one closed off an approach that looked obvious.

1. Running pytest in CI would be red forever. 10 of 27 tests are falsification stubs, red by designdocs/contributor_protocols/carbon_based_agents.md §1: "must not be deleted to make a gate pass." There is no pytest.ini, no conftest.py, no markers. The only thing distinguishing a guard from a stub today is the filename prefix, and ADR-003 (authority of declarations over inference) forbids building on that.

2. The guards split cleanly in two. test_registry_reader_contract.py reads only this repo's registry and runs anywhere. test_registry_readers_agree.py needs sibling checkouts.

3. On a lone runner the cross-repo file fails honestly. Simulated: test_at_least_one_reader_is_present FAILS, four skip. The anti-vacuity guard works — but a naive pytest step would be red for the wrong reason.

4. Two of the three siblings are PUBLIC. views-models and views-crafdapi are public; only views-faoapi is private. Verified via the API.

5. Those two are enough to be meaningful. They genuinely diverge — views-models has _is_planned(), crafdapi does not — so the D-05 divergence is visible in CI without any token.

6. CI is a stronger environment than a laptop. The behavioural tests need tomllib (Python ≥3.11); local python here is 3.10, so they skip locally. GitHub runners ship 3.12. Verified under 3.11 with both public siblings present: 15 passed / 2 xfailed / 10 stubs red — every guard ran.

7. validate_docs.sh check 8 would SKIP in CI. It compares against origin/main, and actions/checkout does not reliably create that ref. Its skip prints a note and exits 0. Adding the script to CI naively produces a green that silently excludes the version check. This is the sharpest vacuity trap in the epic — the fix for C-53 would be present but not running, which is exactly the failure this epic is about.

Desired end state

Every guard this repository has runs on every pull request, in a way that cannot pass vacuously; the falsification stubs stay visible without blocking; and the discipline that produced these guards is written down rather than remembered.

Scope

In scope

  • Declaring guards and stubs as distinct kinds, by marker not filename
  • A blocking CI job for the self-contained guards + validate_docs.sh
  • A blocking CI job for the cross-repo guard, with the public siblings checked out
  • A non-blocking reporting job for the falsification stubs
  • Making every "could not check" an explicit failure
  • Recording the mutation-proof convention
  • Tracking the views-faoapi token as a known, blocked gap

Out of scope, deliberately

  • ruff/pytest gates for package code. There is no package. That is [þing-01][DEFERRED] Scaffold + reference validator (trigger: operator ∧ test project) #8's scaffold, deferred by ratified decision (dómr_endurmat E6) behind operator ∧ test project — and the test project is now confirmed not to exist (þing-02 A3(h), answered 2026-08-05). C-02 stays open.
  • views-models#330 (C-62 — platform_env_validate() is circular). Same cluster, another repo.
  • Settling D-05 (views-models#327). The cross-repo guard reports the divergence; it does not resolve it.
  • Adding new guards. This epic runs the ones that exist.
  • secret_scan.yml itself. It works, it is mutation-proven, and it is the operator's.

Stories

# Story Depends on
S1 Declare guards and falsification stubs as distinct kinds
S2 CI job: self-contained guards + validate_docs.sh, blocking S1
S3 CI job: cross-repo guard with public siblings checked out S1, S2
S4 CI job: falsification stubs, non-blocking, reporting-only S1
S5 Make the checks required, and prove the whole thing bites S2, S3, S4
S6 Record the convention: a guard is not finished until it has been shown to fail S1–S5
S7 views-faoapi is private — the token that completes the comparison blocked

Order: S1 → S2 → S3 → S4 → S5 → S6. S7 runs in parallel, blocked on operator item #12(l).

Why S1 first: every later story needs to select "the guards" without inferring from a filename.

Why S5 last: making a check required before it has been proven to bite would repeat the exact error this epic exists to fix.

Epic acceptance criteria

  • Every guard runs on every PR — 5 registry-shape tests, 6 reader-agreement tests, 8 doc checks
  • A guard that cannot run fails the build. Specifically: validate_docs.sh check 8 with no reachable origin/main, and a declared reader whose repo is checked out but whose file is absent
  • Re-introducing commit 2186d45's shape — a value-less [target] entry — turns CI red
  • Falsification stubs are visible in CI, block nothing, and their count is reported so a stub turning green is noticed (that is how C-68 was caught)
  • The ruleset's required-checks list names the new jobs
  • Every claim above is mutation-proven, not asserted
  • views-faoapi's absence is a recorded, tracked gap rather than an invisible one

Tracking

Concern: C-70 (Tier 2), cluster G in reports/technical_risk_register.md.
Related: #8 (deferred scaffold — explicitly not this epic), #12 item (l) (the CI token, blocks S7), views-models#330 (C-62, sibling instance of the same cluster).

Metadata

Metadata

Assignees

No one assigned

    Labels

    epicLarge body of work broken into storiesplanningDecision or design work, no code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions