You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(governance): promote the docs + package-policy gates from theatre to real (#505) (#513)
Promotes the two `governance-reusable.yml` jobs that **could not fail**
into real gates — tasks 1, 2 and 3 of #505.
## Blast radius was measured first, not guessed
Over the **412 real repo-root callers** of `governance-reusable` in the
estate checkout (1,106 raw grep hits reduce to 412 once nested monorepo
subdirs — whose `.github/workflows` GitHub never reads — are excluded):
| check | missing | decision |
|---|---|---|
| README | **0 / 412** | **blocking now** — arming reds nobody |
| LICENSE | **0 / 412** | **blocking now** — arming reds nobody |
| CONTRIBUTING | 54 / 412 (13%) | warn → **blocking from 2026-08-21** |
| no Guix/Nix packaging | 70 / 412 (17%) | warn → **blocking from
2026-08-21** |
**Verified against all 412 callers with the final scripts: 0 red today
on both gates.** The grace window buys time without manufacturing red
noise now — and it is a *real date that flips itself*, not a flag
defaulting to off (which would be the theatre this replaces).
**94 unique repos** must land a `CONTRIBUTING` and/or packaging file
before the cutoff. Full list attached as a comment below.
## What changed
**`scripts/check-docs-presence.sh`** (new) — replaces the
`::warning::`-only step. Split gate: README+LICENSE fail immediately,
CONTRIBUTING warns until the cutoff. Critically, it **never prints a
pass claim while a required file is absent** — grace mode prints `NOT
YET ENFORCED`, not a green tick.
**`scripts/check-package-policy.sh`** (new) — replaces the job that
ended in an unconditional `✅ Package policy check passed`. Two honesty
fixes beyond adding `exit 1`:
- Predicate tightened from *"any `*.scm` anywhere"* (a stray Guile
source file satisfied it) to a genuine packaging artefact
(`guix.scm`/`manifest.scm`/`channels.scm`/`.guix-channel`). Tightening
moved only **13** repos, so honesty was nearly free.
- Vendored trees (`node_modules/`, `deps/`, `.lake/`, `vendor/`,
`.git/`) are pruned, so a dependency can't satisfy the policy on the
caller's behalf.
- The `git diff HEAD~1` lockfile branch is **dropped, not stubbed**: it
never resolved under `ref: github.sha` without `fetch-depth`, so it was
inert. hypatia `cicd_rules/nodejs_detected` is the real rule. Broadening
it beyond `package-lock.json` is follow-up, noted below.
**Redundant trufflehog removed** (#505 task 3). It was
`continue-on-error: true` so it never gated, and it duplicated the real
gitleaks gate from #500. `secret-scanner-reusable.yml`'s header
*already* claimed "Trufflehog removed as redundant" — this reconciles
the estate with itself. Removing a never-failing step cannot newly-red
any caller.
**Both gates refuse to be disarmed.** A malformed cutoff would make the
date comparison pick the grace branch forever — silently restoring the
fake gate. Both scripts validate their own cutoff format and hard-fail
on garbage.
## A real bug, found only by running against real repos
`find … | head -1` under `set -o pipefail` is a **SIGPIPE race**: `head`
exits after line 1, `find` keeps writing, takes SIGPIPE, and `pipefail`
propagates it — aborting under `set -e`. It only bites on trees large
enough that `find` is still running, so **all 20 unit fixtures passed
while two real estate repos red intermittently for no policy reason**.
Fixed, with a regression test that was itself red-teamed: it *fails*
against the buggy form and passes against the fix. (The first version of
that test was a false-green — 3,000 non-matching files don't trigger it,
because `find` emits one line; the fixture now creates 4,000 *matching*
paths.)
## Verification
`just governance-gates-test` → **21 cases, all green**. Drives both
gates on **both sides of the cutoff** (`DOCS_TODAY` / `PKG_TODAY`
seams), plus alternate extensions, inclusive-cutoff boundary,
vendored-tree pruning, stray-`.scm` rejection, malformed-cutoff refusal,
and the SIGPIPE regression.
This matters because **#505 notes standards CI does not exercise the
reusable for SHA-pinned callers** — watching this repo go green proves
nothing about them. Note however that **396 callers pin `@main`**, so
they pick this up *immediately on merge*; the grace window is what makes
that safe.
## ⚠️ Reviewer note — the plumbing proof and the expected red
standards calls this reusable **on its own PRs** (`governance.yml` →
`./.github/workflows/governance-reusable.yml`), and the script checkout
is pinned `ref: main`. The new scripts are not on `main` until this
merges, so the final commit's governance run **will red for that reason
alone, not because the change is broken**.
To prove the plumbing (sparse-checkout → `cp` to `$RUNNER_TEMP` → `rm
-rf .standards-checkout` → run) actually works end-to-end, this branch
temporarily points `ref:` at itself; that run is the evidence, and the
`ref:` is reverted to `main` before merge. See the commit history.
## Rollback
Revert this PR, or re-pin callers to the previous `governance-reusable`
SHA. The two new scripts are additive — nothing else calls them.
## Follow-up (not in scope here)
- Broaden hypatia `cicd_rules/nodejs_detected` beyond
`package-lock.json` (yarn/Gemfile/Pipfile/poetry lockfiles), recovering
the coverage the inert branch nominally claimed.
- The 94-repo remediation list before 2026-08-21.
Refs #505, #500
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
0 commit comments