testsAndMisc/docs/superpowers/contracts/phase2-cap-and-ci-gates-2026-08-21.json
Krzysztof kuhy Rudnicki 1d7271f023 Phase 2: enforce the 250-line cap and stop pushing red
Two pre-commit hooks and one pre-push extension, plus the _glyph_art split
that had to land first — the cap gate cannot be wired while any file is over
it, and the lyricanki note-ascender glyph had taken _glyph_art.py to 253.

file-length-cap runs check_file_length.sh --all repo-wide rather than on
staged files, so a file that grows past the cap in some other commit is still
caught. Proven to block, not assumed: with a deliberate 261-line file staged
the hook exits 1 and names it; with the file removed it passes.

ci-baseline-green is the user's option (a): refuse to build on a main that is
already red. It fails closed on a definitively failing baseline and warns-and-
passes on anything it cannot determine — offline, no gh, unauthenticated, no
settled runs — each call capped at 5s. Blocking every commit on network
reachability buys nothing when (b) is the real per-change guarantee.
CI_GREEN_SKIP=1 is the escape for a fix-forward commit. python-tests.yml is
excluded on purpose: it is path-filtered, so a shell-only commit never
triggers it and its "latest run" would produce false reds.

This hook already earned its place. Run against a red main earlier in this
session it refused with "Shell tests (failure)", which is how the broken
SETUP_SOURCES was found instead of being pushed over.

ci_mirror gains the shell-tests workflow's side-effect-free half — every
lib/tests/run_all.sh plus the workflow's own test list, the user's option (b).
That list is parsed out of shell-tests.yml rather than copied: a hardcoded
duplicate drifts the moment someone adds a test, and a mirror that quietly
checks less than CI is worse than no mirror because it reports safe. The
Arch-container half stays unmirrored — it wants root and an Arch userland.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F3PzGc75gBcdxP3PkHXGcV
2026-08-21 16:41:31 +02:00

18 lines
1.8 KiB
JSON

{
"title": "Phase 2: enforce the 250-line cap and mirror Shell tests before push",
"objective": "Make the 250-line cap a gate rather than a convention, and close the loop that let shell changes pass every local check and still go red on push. Implements both halves of the user's answer to the CI-green fork: (a) refuse to build on a red main, (b) run the Shell tests workflow's local equivalent on pre-push.",
"acceptance_criteria": [
"check_file_length.sh --all reports zero violations before the hook is wired; the gate must not land while any file is over the cap.",
"The file-length hook demonstrably BLOCKS a deliberately over-cap file and passes once it is removed — proven, not assumed.",
"The CI-baseline hook fails closed on a definitively red required workflow and exits 0 on every undeterminable case: no gh, unauthenticated, offline, inside GitHub Actions, CI_GREEN_SKIP=1.",
"ci_mirror runs every lib/tests/run_all.sh and the workflow's side-effect-free test list, with that list derived from shell-tests.yml rather than duplicated, and fails if the derivation yields nothing.",
"shellcheck passes on both scripts with no suppression added."
],
"out_of_scope": [
"Mirroring the Arch-container half of shell-tests: it needs root and an Arch userland.",
"Requiring python-tests.yml to be green — it is path-filtered and would produce false reds on shell-only commits.",
"Phase 3, the repo-wide shell coverage gate, which the user has not yet scoped."
],
"verifier": "pre-commit run file-length-cap --all-files with a 261-line probe staged (must exit 1 naming the file) and again after removing it (must pass); pre-commit run ci-baseline-green --all-files against green main, plus the CI_GREEN_SKIP and GITHUB_ACTIONS skip paths; the awk parse compared against the workflow's own list; shellcheck on both scripts."
}