Skip to content

[guard.contract.mu.D8+] the gate went red within the hour, on four ke… #38

[guard.contract.mu.D8+] the gate went red within the hour, on four ke…

[guard.contract.mu.D8+] the gate went red within the hour, on four ke… #38

Workflow file for this run

name: Dirac gates
# Triggers on EVERY branch, deliberately. The two pre-existing workflows
# (node.yml, docs.yml) are pinned to `branches: master`, but this repo's branch
# is `main` — so neither has ever run a single time. Unqualified `push` cannot
# repeat that mistake.
on:
push:
pull_request:
# A second push to the same branch cancels the first: these gates are cheap, but
# not free, and only the tip matters.
concurrency:
group: dirac-gates-${{ github.ref }}
cancel-in-progress: true
jobs:
gates:
name: S1 gates
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
# package.json engines says node >=22.0.0. Pinned to the major rather than
# resolved from the range: a range silently follows the newest release, so
# a green CI could turn red without a single commit.
- name: Node 22
uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
# design/check_palette.py imports only math, re, sys and pathlib — all
# stdlib. There is deliberately no pip install step; adding one would be a
# dependency this suite does not have.
- name: Python 3.12
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: npm ci
id: npm_ci
run: npm ci
# ---- the four gates, one step each, so a failure names itself ----------
- name: 'Gate 1 — typecheck (tsc --noEmit)'
if: ${{ !cancelled() && steps.npm_ci.outcome == 'success' }}
run: node_modules/.bin/tsc --noEmit -p tsconfig.json
- name: 'Gate 2 — build dirac (production)'
if: ${{ !cancelled() && steps.npm_ci.outcome == 'success' }}
run: node ./scripts/build.mjs -a dirac --prd
# Gates 3 and 4 touch neither node_modules nor the build output, so they
# run even when the install or an earlier gate failed. One red gate must
# not hide the other three.
- name: 'Gate 3 — palette chroma / contrast / ΔE'
if: ${{ !cancelled() }}
run: python3 design/check_palette.py
- name: 'Gate 4 — CSS brace balance (regression: a93c175)'
if: ${{ !cancelled() }}
run: node scripts/check_css_braces.mjs src/app.frontend.facets.molstar-rdkit.editable/index.html
# Gates 6-8 were running locally and NOWHERE ELSE, which makes them
# advice rather than gates. All three are pure node, need no database and
# no build output, so they run unconditionally like 3 and 4. Gate 5
# (migration hashes) still cannot run here: it needs the applied ledger,
# and a version that passes without a database would be a check that
# cannot fail.
- name: 'Gate 6 — doc facts re-derived from source'
if: ${{ !cancelled() }}
run: node scripts/check_docs_facts.mjs
# Exit 2 = contracts clean, src/ behind. Reported, not fatal: the frontend
# interface is owned elsewhere and legitimately trails. Exit 1 (contracts
# disagree with the code) fails the build.
- name: 'Gate 7 — contract drift (errors.json / iface.* / FIELD_META_SCHEMA)'
if: ${{ !cancelled() }}
run: |
node scripts/check_contract_drift.mjs --redproof
node scripts/check_contract_drift.mjs; code=$?
if [ "$code" = "1" ]; then exit 1; fi
if [ "$code" = "2" ]; then echo "::warning::frontend FieldMeta trails the backend (see FIND lines)"; fi
exit 0
# The selftest runs FIRST and its failure is the gate's failure: this one
# is green against the real files, so a crafted broken source is the only
# evidence it has resolution at all.
- name: 'Gate 8 — every physics SCF route carries all four protections'
if: ${{ !cancelled() }}
run: |
node scripts/check_physics_contract.mjs --selftest
node scripts/check_physics_contract.mjs