5353 name : Swift Runner Unit Compile
5454 runs-on : macos-26
5555 timeout-minutes : 20
56+ # Was an inline `VAR=1 pnpm gate …` prefix on the action's build-command input. The
57+ # input is a gate id now, so the variable lives where ios.yml already puts it: the job.
58+ env :
59+ AGENT_DEVICE_XCUITEST_INCLUDE_UNIT_TESTS : ' 1'
5660 steps :
5761 - name : Checkout
5862 uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
6569 with :
6670 derived-path : ${{ github.workspace }}/.tmp/swift-runner-unit-derived
6771 cache-key-prefix : swift-runner-unit
68- build-command : AGENT_DEVICE_XCUITEST_INCLUDE_UNIT_TESTS=1 pnpm build:xcuitest: macos
72+ gate : swift-runner- macos
6973 xcuitest-platform : macos
7074 xcuitest-destination : platform=macOS,arch=arm64
7175
@@ -81,10 +85,10 @@ jobs:
8185 uses : ./.github/actions/setup-node-pnpm
8286
8387 - name : Run oxlint
84- run : pnpm lint
88+ run : pnpm gate lint
8589
8690 - name : Check formatting
87- run : pnpm format:check
91+ run : pnpm gate format
8892
8993 layering-guard :
9094 name : Layering Guard
@@ -107,14 +111,28 @@ jobs:
107111 # Generalizes the former inline commands/-import grep into a structured
108112 # import-direction lint over the resolved graph. See scripts/layering/check.ts
109113 # and CONTEXT.md (Architecture: folder DAG + layering lint).
110- run : pnpm check: layering
114+ run : pnpm gate layering
111115
112116 - name : Check the depgraph report agrees with the gate
113117 # scripts/depgraph reads the same model as the gate, so its inversion count must
114118 # reproduce TYPE_INVERSION_BASELINE. Free two-sources check: if the tree changes
115119 # and only one side is updated, this fails and names the difference. Runs here
116120 # rather than in its own job so the two can never be green independently.
117- run : pnpm depgraph:test
121+ run : pnpm gate depgraph
122+
123+ # The TMPDIR redirection both test lanes rely on (#1593/#1595). Its own tests ran
124+ # in no CI job at all until the #1429 gate manifest found them unowned.
125+ #
126+ # Deliberately NOT in the Coverage job next to `check:tmpdir-leaks`, where the
127+ # subject matter would put it: vitest-tmpdir-global-setup.test.ts proves the
128+ # lifecycle by spawning a real nested `vitest run`, and the Coverage lane already
129+ # loses runs to `[vitest-pool]: Worker forks emitted error` when a fork is slow to
130+ # terminate (observed on main at 18291ba8, unrelated to this gate). Starting a
131+ # nested Vitest seconds before the full instrumented suite is a contention risk
132+ # with nothing to gain — the manifest proves ownership per unit of work, so any
133+ # lane satisfies it.
134+ - name : Check the tmpdir redirection model
135+ run : pnpm gate tmpdir-leaks-model
118136
119137 affected-selector :
120138 name : Affected-check Selector
@@ -135,7 +153,18 @@ jobs:
135153 # The selector is fail-open and advisory (GitHub CI stays authoritative),
136154 # so the gate only guards the derivation model.
137155 - name : Check affected-selector model
138- run : pnpm check:affected:test
156+ run : pnpm gate affected-selector
157+
158+ # The gate-of-gates (#1429). It shares this job because it validates the
159+ # same artifact the selector is built on — CHECK_CATALOG's `ciJobs` — and
160+ # because a gate that proves the other gates are wired must not be the one
161+ # gate sitting in its own job, green on its own. Deterministic and
162+ # network-free: every input is a file in the checkout.
163+ - name : Check the gate manifest model
164+ run : pnpm gate gate-manifest-model
165+
166+ - name : Check every gate is owned, wired, and reachable
167+ run : pnpm gate gate-manifest
139168
140169 maestro-conformance :
141170 name : Maestro Conformance Oracle
@@ -157,7 +186,7 @@ jobs:
157186 # device-backed layer 3 runs on the scheduled conformance-differential
158187 # workflow. See scripts/maestro-conformance/README.md.
159188 - name : Verify Maestro conformance fixtures
160- run : pnpm maestro: conformance
189+ run : pnpm gate maestro- conformance
161190
162191 packaged-cli-node-22-12 :
163192 name : Packaged CLI Node 22.12
@@ -172,8 +201,8 @@ jobs:
172201
173202 - name : Build CLI
174203 run : |
175- pnpm build
176- pnpm check: bundle-owner-files
204+ pnpm gate build
205+ pnpm gate bundle-owner-files
177206
178207 # The build runs on the default toolchain Node and the package is verified on the minimum
179208 # supported Node, so this job covers what a user on `engines.node` floor actually installs.
@@ -207,10 +236,10 @@ jobs:
207236 - name : Run Fallow audit
208237 env :
209238 FALLOW_BASE : ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
210- run : pnpm check: fallow --base "$FALLOW_BASE"
239+ run : pnpm gate fallow --base "$FALLOW_BASE"
211240
212241 - name : Check for production-unused exports
213- run : pnpm check: production-exports
242+ run : pnpm gate production-exports
214243
215244 replay-compat-provenance :
216245 # The frozen replay-compat corpus (#1417) claims each entry was published by
@@ -230,7 +259,7 @@ jobs:
230259 uses : ./.github/actions/setup-node-pnpm
231260
232261 - name : Verify corpus entries against their released blobs
233- run : pnpm check: replay-compat
262+ run : pnpm gate replay-compat
234263
235264 released-surface-compat :
236265 # The daemon RPC wire ledger (#1432) is compared against the ledger as it
@@ -251,10 +280,10 @@ jobs:
251280 uses : ./.github/actions/setup-node-pnpm
252281
253282 - name : Verify the wire-compat rules
254- run : pnpm check:daemon- wire-compat:test
283+ run : pnpm gate wire-compat-model
255284
256285 - name : Compare the daemon RPC wire surface against the last released tag
257- run : pnpm check: daemon-wire-compat
286+ run : pnpm gate daemon-wire-compat
258287
259288 coverage :
260289 # Runs the full unit + provider-integration suites under coverage with
@@ -272,20 +301,29 @@ jobs:
272301 uses : ./.github/actions/setup-node-pnpm
273302
274303 - name : Test changed-line coverage gate
275- run : pnpm check: coverage-changed:test
304+ run : pnpm gate coverage-model
276305
277306 # The retry list is an enumerated set of owned waivers, so an expired entry
278307 # must fail before the suite runs rather than quietly keeping its retry.
279308 - name : Check contention retry policy
280- run : pnpm check: contention-retry
309+ run : pnpm gate contention-retry
281310
282311 # Wrapped in the single-retry policy (#1419): a timeout-shaped failure in
283312 # an enumerated contention-flaky file reruns that file once and reports it
284313 # in the job summary. Assertion failures fail here on the first run.
285314 - name : Run coverage
286315 env :
287316 OUTPUT_ECONOMY_BASE : ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
288- run : pnpm test:coverage:ci
317+ run : pnpm gate unit-ci
318+
319+ # A run whose globalTeardown never fired (crash, OOM, timeout kill) leaves
320+ # its tmpdir behind. `check:unit` runs this locally after the suite; until
321+ # #1429 nothing ran it in CI, which is the environment where those kills
322+ # actually happen. Runs even on failure — a killed run is exactly the case
323+ # worth reporting.
324+ - name : Check for leaked test tmpdirs
325+ if : always()
326+ run : pnpm gate tmpdir-leaks
289327
290328 - name : Upload contention-retry envelope
291329 if : always()
@@ -303,7 +341,7 @@ jobs:
303341 if : always() && github.event_name == 'pull_request'
304342 env :
305343 AGENT_DEVICE_COVERAGE_WAIVER : ${{ contains(github.event.pull_request.labels.*.name, 'coverage-waiver') }}
306- run : pnpm check: coverage-changed --base "${{ github.event.pull_request.base.sha }}"
344+ run : pnpm gate coverage --base "${{ github.event.pull_request.base.sha }}"
307345
308346 typecheck :
309347 name : Typecheck
@@ -317,7 +355,14 @@ jobs:
317355 uses : ./.github/actions/setup-node-pnpm
318356
319357 - name : Run typecheck
320- run : pnpm typecheck
358+ run : pnpm gate typecheck
359+
360+ # CHECK_CATALOG has always claimed this job mirrors the `mcp-metadata`
361+ # check; until #1429 checked the claim, no PR job ran it at all, so
362+ # server.json/smithery.yaml drift only surfaced at publish time (where
363+ # publish-mcp-registry.yml duplicates the same command). Parse-only.
364+ - name : Check MCP registry metadata is in sync
365+ run : pnpm gate mcp-metadata
321366
322367 freerange :
323368 name : FreeRange
@@ -334,7 +379,7 @@ jobs:
334379 uses : oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
335380
336381 - name : Check numeric ranges
337- run : pnpm check: freerange
382+ run : pnpm gate freerange
338383
339384 integration :
340385 name : Integration Tests
@@ -350,27 +395,33 @@ jobs:
350395 - name : Run integration tests
351396 run : |
352397 pnpm clean:daemon
353- pnpm test: integration: node
398+ pnpm gate integration- node
354399
355400 - name : Run seeded concurrency torture lane (fast PR sweep)
356401 # #1416's nightly torture lane lives under test/integration/nightly/, out
357402 # of the test:integration:node glob, so this is a *deliberate* fast PR
358403 # sweep (TORTURE_RUNS default 128 seeds, ~sub-second) — not an accidental
359404 # glob inclusion. The Concurrency Torture Nightly workflow sweeps a much
360405 # larger seed range on schedule.
361- run : pnpm test: concurrency-torture
406+ run : pnpm gate concurrency-torture
362407
363408 - name : Run provider-backed integration tests
364- run : pnpm test:integration: provider
409+ run : pnpm gate provider-integration
365410
366411 - name : Check Provider-backed integration architecture progress
367- run : pnpm test: integration: progress:check
412+ run : pnpm gate integration- progress
368413
369414 # A build-cache lookup outage must degrade setup-fixture-app to an inline
370415 # build, not fail the caller. This drives that step's real shell against a
371416 # failing `gh`.
372417 - name : Setup-fixture-app cache-failure fallback
373- run : sh ./test/scripts/setup-fixture-app-fallback-smoke.sh
418+ run : pnpm gate fixture-fallback
419+
420+ # The trust rules that decide whether a cached fixture APK/app may be
421+ # reused at all — same subject as the fallback smoke above, and parse-only.
422+ # Ran in no CI job until the #1429 gate manifest found it unowned.
423+ - name : Check trusted fixture-artifact selection
424+ run : pnpm gate fixture-cache
374425
375426 web-smoke :
376427 name : Web Platform Smoke
@@ -390,7 +441,7 @@ jobs:
390441 - name : Run live web smoke
391442 run : |
392443 pnpm clean:daemon
393- pnpm test:smoke: web
444+ pnpm gate web-smoke
394445
395446 - name : Upload web smoke artifacts
396447 if : always()
0 commit comments