Skip to content

test: per-spec compile gates in CI; tied-head alias assert #323

test: per-spec compile gates in CI; tied-head alias assert

test: per-spec compile gates in CI; tied-head alias assert #323

Workflow file for this run

name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check:
name: typecheck · unit · build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
env:
# No browser needed in this job — skip Puppeteer's ~150MB Chrome download.
PUPPETEER_SKIP_DOWNLOAD: '1'
# `lint` was an alias for `typecheck` — there is no ESLint config in this
# repo. Calling typecheck directly says what actually runs.
- run: npm run typecheck # tsc --noEmit for src + tests/config (tsconfig.tests.json)
# Tokenizer unit tests are fully offline: fixtures.json + tokenizer.json
# are committed under tests/tokenizer/.
- run: npm run test:unit
- run: npm run build
# e2e tests use Puppeteer + WebGPU which Ubuntu runners don't expose;
# run locally with `npm run test:e2e`.
gates:
name: mutation gate · release checklist
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: '1'
# A green suite looks the same whether it is checking something or not.
# This reinstates each bug that actually shipped and asserts the suite goes
# red — and, since 2026-08-22, that the test whose NAME claims the defect
# is AMONG the failures. Membership, not exclusivity: other tests may fire
# too and that is accepted. What it catches is a defect covered ONLY
# incidentally, where the named check never fires at all and could be
# deleted tomorrow unnoticed.
#
# It was written months before this job existed and ran only when someone
# remembered. FreeToken's tests/README.md names the failure mode: "a gate
# nobody trips rots silently" — and FreeToken then does not run its own
# gates in CI, so its 17/17 score is a fact about one afternoon rather
# than a property of the repo. ~40s here; if it outgrows the PR budget,
# move it to `schedule:` rather than deleting it. (The ~40s was measured on
# the author's machine, not on this runner.)
- run: node scripts/mutation-gate.mjs
# Prints the checklist INCLUDING what this runner cannot run. UNRUN is not
# a pass, so the GPU-only gates stay visible in every PR log instead of
# being remembered. Exits 0 — it is a report, not a gate.
- run: node scripts/release-check.mjs --list
kernels:
name: kernel correctness (lavapipe)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
# Mesa's lavapipe: a CPU Vulkan device with shader-f16, so the real WGSL
# kernels run without a GPU (see tests/kernels/README.md). Subgroup
# variants SKIP loudly if lavapipe lacks the feature/lane width.
- run: sudo apt-get update && sudo apt-get install -y mesa-vulkan-drivers
- run: npm ci
env:
PUPPETEER_SKIP_DOWNLOAD: '1'
- run: npm run test:kernels
env:
VK_ICD_FILENAMES: /usr/share/vulkan/icd.d/lvp_icd.json
# Every shipped spec's shaders must build under its own dims (prelude
# consts, workgroup layouts, u32 address math) — a prelude edit that
# breaks another spec fails here, not in a browser. No weights, no
# numerics; sg-only shaders skip loudly on lavapipe like run.mjs.
- run: npm run test:kernels:all-specs
env:
VK_ICD_FILENAMES: /usr/share/vulkan/icd.d/lvp_icd.json
routing:
name: room routing (no GPU)
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
env:
# No browser needed — plain WebSocket clients, no Puppeteer Chrome.
PUPPETEER_SKIP_DOWNLOAD: '1'
# Warm npx's wrangler download: cold, npx fetching wrangler plus
# workerd's first-run binary fetch exceeds the test's startup budget
# and the relay never comes up. Same VM filesystem, so the test's own
# `npx wrangler dev` below reuses this cache.
- run: npx -y wrangler --version
# Multi-host assignment/relay/takeover against wrangler dev. Seconds,
# deterministic, zero hardware excuse — this ran only when a human
# remembered, and that is how routing regresses silently.
- run: node scripts/room-routing-test.mjs
e2e-lavapipe:
name: browser e2e (lavapipe, no subgroups)
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
# Same software Vulkan as the kernels job, but through real Chrome:
# headful under xvfb so the GPU process gets a display, ICD pinned to
# lavapipe so a missing adapter fails loud instead of silently CPU-ing
# somewhere unobserved. Deliberately the weightless UI tests only:
# entrance-motion's pixel assertions are display-sensitive (0.05px
# tolerances fail under software rasterization) and the Phi-3 battery
# times out (300s/test on lavapipe) — both stay human-shell with real
# GPUs. Mirror-gated spec suites are not collected here, so every
# collected test is expected to RUN.
- run: sudo apt-get update && sudo apt-get install -y mesa-vulkan-drivers xvfb
# No PUPPETEER_SKIP_DOWNLOAD: this job needs the real Chrome download.
- run: npm ci
- run: xvfb-run -a npx vitest run tests/e2e/gate.test.ts tests/e2e/boot-card-fits-the-panel.test.ts --reporter=default --reporter=json --outputFile=/tmp/e2e-lavapipe.json
env:
VK_ICD_FILENAMES: /usr/share/vulkan/icd.d/lvp_icd.json
# Ubuntu 24.04 runners disable unprivileged user namespaces — see harness.ts.
ZTVM_CHROME_NO_SANDBOX: '1'
# vitest exits 0 on skips, so a suite that runs nothing reports green.
# Any skip here is either a regression or a new mirror gate — both must
# be named in scripts/ci-skip-allowlist.json with a reason, or fixed.
- run: node scripts/check-vitest-skips.mjs /tmp/e2e-lavapipe.json