test(pipeline): gate the four failures that shipped silently #116

Merged
peterswimm merged 1 commit from feat/pipeline-gates into main 2026-09-10 17:27:45 +00:00
Owner

Five things shipped this cycle that looked right and weren't, and every one was caught by a human staring at a screenshot rather than by a gate. This adds the gates.

gate the bug it would have caught
cross-brand leak toilville/hero-home shipped in four other brands' patterns for several PRs — the brand-agnostic renderer imported one brand's client
emitted ⊆ allowed_blocks forgeblock_validate only checks the declared direction
client attrs vs block.json an attribute WordPress doesn't know is dropped in silence — the block still renders, just emptier
ritual-demo step states accepted done|active|pending while the vocabulary emits completed|in_progress|pending; two of three fell through and all five steps rendered identically

Each is verified to go red on the reintroduced bug. A gate that has never failed is not evidence of anything, so I reintroduced each one and confirmed the failure before trusting it.

It found real drift on its first run

The allowed_blocks gate went red immediately: toilville emits input (the contact form) and code (the Spelwork terminal) with no allowance in ux.yml. Added both — that's the one-line dist/toilville/artifact.html rebuild in the diff (· code · input on the Deck Landing body region).

⚠️ Gotcha for the next editor: _miniyaml parses flow sequences on one line only. Wrapping that list across two lines makes the parser raise, not degrade.

align_check.py had the sibling-lookup bug for the third time

_ROOT.parent / "Toilville_Rituals" misses inside a git worktree, so both cross-repo audits printed "skipped" while auditing nothing. Same git-common-dir fix already applied to test_forgeblock_grammar.py and build_page.py.

The skip is now loud (⚠ NOT AUDITED) and check mode exits 1 rather than passing on an audit that never ran — a silent skip is precisely what this gate exists to catch. The new cross-repo checks fail rather than skip for the same reason.

Running it for real surfaces 26 raw hex literals in the toilville/* blocks that should be var(--wp--preset--color--*). Informational (report exits 0), not addressed here.

Verification

  • just check green; pytest generator/tests/ tools/wp_theme_ingestor/test_*.py280 passed, 0 skipped
  • Companion PR toilville_rituals#374 adds php -l / node --check on the plugin — that lint belongs in the repo the plugin lives in, since a job here would be permanently skipped.

https://claude.ai/code/session_01Kbzfscp4w5enUrZxMnDt78

Five things shipped this cycle that **looked right and weren't**, and every one was caught by a human staring at a screenshot rather than by a gate. This adds the gates. | gate | the bug it would have caught | |---|---| | cross-brand leak | `toilville/hero-home` shipped in **four** other brands' patterns for several PRs — the brand-agnostic renderer imported one brand's client | | emitted ⊆ `allowed_blocks` | `forgeblock_validate` only checks the *declared* direction | | client attrs vs `block.json` | an attribute WordPress doesn't know is dropped in silence — the block still renders, just emptier | | `ritual-demo` step states | accepted `done\|active\|pending` while the vocabulary emits `completed\|in_progress\|pending`; two of three fell through and all five steps rendered identically | **Each is verified to go red on the reintroduced bug.** A gate that has never failed is not evidence of anything, so I reintroduced each one and confirmed the failure before trusting it. ### It found real drift on its first run The `allowed_blocks` gate went red immediately: toilville emits `input` (the contact form) and `code` (the Spelwork terminal) with no allowance in `ux.yml`. Added both — that's the one-line `dist/toilville/artifact.html` rebuild in the diff (`· code · input` on the Deck Landing body region). ⚠️ **Gotcha for the next editor:** `_miniyaml` parses flow sequences on **one line only**. Wrapping that list across two lines makes the parser raise, not degrade. ### `align_check.py` had the sibling-lookup bug for the third time `_ROOT.parent / "Toilville_Rituals"` misses inside a git worktree, so **both** cross-repo audits printed "skipped" while auditing nothing. Same `git-common-dir` fix already applied to `test_forgeblock_grammar.py` and `build_page.py`. The skip is now loud (`⚠ NOT AUDITED`) and `check` mode **exits 1 rather than passing on an audit that never ran** — a silent skip is precisely what this gate exists to catch. The new cross-repo checks fail rather than skip for the same reason. Running it for real surfaces **26 raw hex literals** in the `toilville/*` blocks that should be `var(--wp--preset--color--*)`. Informational (`report` exits 0), not addressed here. ### Verification - `just check` green; `pytest generator/tests/ tools/wp_theme_ingestor/test_*.py` → **280 passed, 0 skipped** - Companion PR toilville_rituals#374 adds `php -l` / `node --check` on the plugin — that lint belongs in the repo the plugin lives in, since a job here would be permanently skipped. https://claude.ai/code/session_01Kbzfscp4w5enUrZxMnDt78
test(pipeline): gate the four failures that shipped silently
Some checks failed
PR policy check / policy-gate (pull_request) Failing after 0s
Security Scans / Trivy filesystem scan (pull_request) Successful in 11m48s
Security Scans / Gitleaks secret scan (pull_request) Successful in 8m55s
Test Generator / test (pull_request) Failing after 10m20s
Test Generator / lint-workflows (pull_request) Successful in 8m6s
Test Generator / lint-prose (pull_request) Successful in 8m33s
UDG dist drift gate / dist/ matches dtcg + udg sources (pull_request) Successful in 6m38s
1a532e57cc
Every check here is a bug that reached main and was caught by a human looking at
a rendered page. Each one is verified to go RED on the reintroduced bug — a gate
that has never failed is not evidence of anything.

  * cross-brand leak — `toilville/hero-home` shipped in spelwork, pardner, tctd
    and fux-capacity patterns for several PRs because the brand-agnostic renderer
    imported one brand's client. Parametrised per brand; red on an injected
    foreign block.

  * emitted blocks vs allowed_blocks — forgeblock_validate checks that DECLARED
    allowed_blocks name real vocabulary blocks, never the reverse. This supplies
    that direction, and caught real drift on its first run: toilville emits
    `input` (the contact form) and `code` (the Spelwork terminal) with no
    allowance. Added both to ux.yml, hence the artifact rebuild.

    Note for the next editor: _miniyaml parses flow sequences on ONE line only.
    Wrapping that list across two lines makes the parser raise, not degrade.

  * client attributes vs the target block — an attribute WordPress does not know
    is dropped in silence; the block still renders, just emptier. Cross-checks
    every emitted attribute against the plugin's block.json.

  * ritual-demo's step states — it accepted done|active|pending while the
    vocabulary emits completed|in_progress|pending, so two of three fell through
    to the default and all five steps rendered identically. Now asserts the
    render.php $alias map covers the whole UDG status enum.

align_check.py had the sibling-lookup bug for the third time: `_ROOT.parent /
"Toilville_Rituals"` misses inside a worktree, so BOTH cross-repo audits printed
"skipped" while auditing nothing. Same git-common-dir fix as
test_forgeblock_grammar.py and build_page.py. The skip line now reads "⚠ NOT
AUDITED", and `check` mode exits 1 rather than passing on an audit that never
ran — a silent skip is what this gate exists to catch. Running it for real
surfaces 26 raw hex literals in the toilville/* blocks (informational).

The cross-repo checks FAIL rather than skip when the plugin is absent, for the
same reason.

Claude-Session: https://claude.ai/code/session_01Kbzfscp4w5enUrZxMnDt78
peterswimm deleted branch feat/pipeline-gates 2026-09-10 17:27:45 +00:00
Sign in to join this conversation.
No description provided.