@@ -85,10 +85,12 @@ jobs:
8585 uses : ./.github/actions/setup-node-pnpm
8686
8787 - name : Run oxlint
88- run : pnpm gate lint
88+ uses : ./.github/actions/run-gate
89+ with : { gate: lint }
8990
9091 - name : Check formatting
91- run : pnpm gate format
92+ uses : ./.github/actions/run-gate
93+ with : { gate: format }
9294
9395 layering-guard :
9496 name : Layering Guard
@@ -111,14 +113,16 @@ jobs:
111113 # Generalizes the former inline commands/-import grep into a structured
112114 # import-direction lint over the resolved graph. See scripts/layering/check.ts
113115 # and CONTEXT.md (Architecture: folder DAG + layering lint).
114- run : pnpm gate layering
116+ uses : ./.github/actions/run-gate
117+ with : { gate: layering }
115118
116119 - name : Check the depgraph report agrees with the gate
117120 # scripts/depgraph reads the same model as the gate, so its inversion count must
118121 # reproduce TYPE_INVERSION_BASELINE. Free two-sources check: if the tree changes
119122 # and only one side is updated, this fails and names the difference. Runs here
120123 # rather than in its own job so the two can never be green independently.
121- run : pnpm gate depgraph
124+ uses : ./.github/actions/run-gate
125+ with : { gate: depgraph }
122126
123127 # Tests for the TMPDIR redirection itself, hidden the same way as the check above.
124128 #
@@ -129,7 +133,8 @@ jobs:
129133 # Starting a nested Vitest seconds before the full instrumented suite is a contention
130134 # risk with nothing to gain.
131135 - name : Check the tmpdir redirection model
132- run : pnpm gate tmpdir-leaks-model
136+ uses : ./.github/actions/run-gate
137+ with : { gate: tmpdir-leaks-model }
133138
134139 affected-selector :
135140 name : Affected-check Selector
@@ -150,18 +155,21 @@ jobs:
150155 # The selector is fail-open and advisory (GitHub CI stays authoritative),
151156 # so the gate only guards the derivation model.
152157 - name : Check affected-selector model
153- run : pnpm gate affected-selector
158+ uses : ./.github/actions/run-gate
159+ with : { gate: affected-selector }
154160
155161 # The gate-of-gates (#1429). It shares this job because it validates the
156162 # same artifact the selector is built on — CHECK_CATALOG's `ciJobs` — and
157163 # because a gate that proves the other gates are wired must not be the one
158164 # gate sitting in its own job, green on its own. Deterministic and
159165 # network-free: every input is a file in the checkout.
160166 - name : Check the gate manifest model
161- run : pnpm gate gate-manifest-model
167+ uses : ./.github/actions/run-gate
168+ with : { gate: gate-manifest-model }
162169
163170 - name : Check every gate is owned, wired, and reachable
164- run : pnpm gate gate-manifest
171+ uses : ./.github/actions/run-gate
172+ with : { gate: gate-manifest }
165173
166174 maestro-conformance :
167175 name : Maestro Conformance Oracle
@@ -183,7 +191,8 @@ jobs:
183191 # device-backed layer 3 runs on the scheduled conformance-differential
184192 # workflow. See scripts/maestro-conformance/README.md.
185193 - name : Verify Maestro conformance fixtures
186- run : pnpm gate maestro-conformance
194+ uses : ./.github/actions/run-gate
195+ with : { gate: maestro-conformance }
187196
188197 packaged-cli-node-22-12 :
189198 name : Packaged CLI Node 22.12
@@ -197,9 +206,12 @@ jobs:
197206 uses : ./.github/actions/setup-node-pnpm
198207
199208 - name : Build CLI
200- run : |
201- pnpm gate build
202- pnpm gate bundle-owner-files
209+ uses : ./.github/actions/run-gate
210+ with : { gate: build }
211+
212+ - name : Verify emitted chunk ownership
213+ uses : ./.github/actions/run-gate
214+ with : { gate: bundle-owner-files }
203215
204216 # The build runs on the default toolchain Node and the package is verified on the minimum
205217 # supported Node, so this job covers what a user on `engines.node` floor actually installs.
@@ -233,10 +245,16 @@ jobs:
233245 - name : Run Fallow audit
234246 env :
235247 FALLOW_BASE : ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
236- run : pnpm gate fallow --base "$FALLOW_BASE"
248+ uses : ./.github/actions/run-gate
249+ with :
250+ gate : fallow
251+ args : |
252+ --base
253+ ${{ env.FALLOW_BASE }}
237254
238255 - name : Check for production-unused exports
239- run : pnpm gate production-exports
256+ uses : ./.github/actions/run-gate
257+ with : { gate: production-exports }
240258
241259 replay-compat-provenance :
242260 # The frozen replay-compat corpus (#1417) claims each entry was published by
@@ -256,7 +274,8 @@ jobs:
256274 uses : ./.github/actions/setup-node-pnpm
257275
258276 - name : Verify corpus entries against their released blobs
259- run : pnpm gate replay-compat
277+ uses : ./.github/actions/run-gate
278+ with : { gate: replay-compat }
260279
261280 released-surface-compat :
262281 # The daemon RPC wire ledger (#1432) is compared against the ledger as it
@@ -277,10 +296,12 @@ jobs:
277296 uses : ./.github/actions/setup-node-pnpm
278297
279298 - name : Verify the wire-compat rules
280- run : pnpm gate wire-compat-model
299+ uses : ./.github/actions/run-gate
300+ with : { gate: wire-compat-model }
281301
282302 - name : Compare the daemon RPC wire surface against the last released tag
283- run : pnpm gate daemon-wire-compat
303+ uses : ./.github/actions/run-gate
304+ with : { gate: daemon-wire-compat }
284305
285306 coverage :
286307 # Runs the full unit + provider-integration suites under coverage with
@@ -298,26 +319,30 @@ jobs:
298319 uses : ./.github/actions/setup-node-pnpm
299320
300321 - name : Test changed-line coverage gate
301- run : pnpm gate coverage-model
322+ uses : ./.github/actions/run-gate
323+ with : { gate: coverage-model }
302324
303325 # The retry list is an enumerated set of owned waivers, so an expired entry
304326 # must fail before the suite runs rather than quietly keeping its retry.
305327 - name : Check contention retry policy
306- run : pnpm gate contention-retry
328+ uses : ./.github/actions/run-gate
329+ with : { gate: contention-retry }
307330
308331 # Wrapped in the single-retry policy (#1419): a timeout-shaped failure in
309332 # an enumerated contention-flaky file reruns that file once and reports it
310333 # in the job summary. Assertion failures fail here on the first run.
311334 - name : Run coverage
312335 env :
313336 OUTPUT_ECONOMY_BASE : ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
314- run : pnpm gate unit-ci
337+ uses : ./.github/actions/run-gate
338+ with : { gate: unit-ci }
315339 # The TMPDIR redirection both test lanes depend on (#1593/#1595). The check is a real
316340 # package script that no workflow ran: it is reachable only through `check:unit`, an
317341 # aggregate CI never invokes, so a leak regression could not fail a PR. Placed here
318342 # because this is the lane whose instrumented suite would leak a run directory.
319343 - name : Check for leaked temp directories
320- run : pnpm gate tmpdir-leaks
344+ uses : ./.github/actions/run-gate
345+ with : { gate: tmpdir-leaks }
321346
322347 - name : Upload contention-retry envelope
323348 if : always()
@@ -335,7 +360,12 @@ jobs:
335360 if : always() && github.event_name == 'pull_request'
336361 env :
337362 AGENT_DEVICE_COVERAGE_WAIVER : ${{ contains(github.event.pull_request.labels.*.name, 'coverage-waiver') }}
338- run : pnpm gate coverage --base "${{ github.event.pull_request.base.sha }}"
363+ uses : ./.github/actions/run-gate
364+ with :
365+ gate : coverage
366+ args : |
367+ --base
368+ ${{ github.event.pull_request.base.sha }}
339369
340370 typecheck :
341371 name : Typecheck
@@ -349,14 +379,16 @@ jobs:
349379 uses : ./.github/actions/setup-node-pnpm
350380
351381 - name : Run typecheck
352- run : pnpm gate typecheck
382+ uses : ./.github/actions/run-gate
383+ with : { gate: typecheck }
353384
354385 # CHECK_CATALOG has always claimed this job mirrors the `mcp-metadata`
355386 # check; until #1429 checked the claim, no PR job ran it at all, so
356387 # server.json/smithery.yaml drift only surfaced at publish time (where
357388 # publish-mcp-registry.yml duplicates the same command). Parse-only.
358389 - name : Check MCP registry metadata is in sync
359- run : pnpm gate mcp-metadata
390+ uses : ./.github/actions/run-gate
391+ with : { gate: mcp-metadata }
360392
361393 freerange :
362394 name : FreeRange
@@ -373,7 +405,8 @@ jobs:
373405 uses : oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
374406
375407 - name : Check numeric ranges
376- run : pnpm gate freerange
408+ uses : ./.github/actions/run-gate
409+ with : { gate: freerange }
377410
378411 integration :
379412 name : Integration Tests
@@ -387,33 +420,40 @@ jobs:
387420 uses : ./.github/actions/setup-node-pnpm
388421
389422 - name : Run integration tests
390- run : |
391- pnpm clean:daemon
392- pnpm gate integration-node
423+ run : pnpm clean:daemon
424+
425+ - name : Execute integration tests
426+ uses : ./.github/actions/run-gate
427+ with : { gate: integration-node }
393428
394429 - name : Run seeded concurrency torture lane (fast PR sweep)
395430 # #1416's nightly torture lane lives under test/integration/nightly/, out
396431 # of the test:integration:node glob, so this is a *deliberate* fast PR
397432 # sweep (TORTURE_RUNS default 128 seeds, ~sub-second) — not an accidental
398433 # glob inclusion. The Concurrency Torture Nightly workflow sweeps a much
399434 # larger seed range on schedule.
400- run : pnpm gate concurrency-torture
435+ uses : ./.github/actions/run-gate
436+ with : { gate: concurrency-torture }
401437
402438 - name : Run provider-backed integration tests
403- run : pnpm gate provider-integration
439+ uses : ./.github/actions/run-gate
440+ with : { gate: provider-integration }
404441
405442 - name : Check Provider-backed integration architecture progress
406- run : pnpm gate integration-progress
443+ uses : ./.github/actions/run-gate
444+ with : { gate: integration-progress }
407445
408446 # A build-cache lookup outage must degrade setup-fixture-app to an inline
409447 # build, not fail the caller. This drives that step's real shell against a
410448 # failing `gh`.
411449 - name : Setup-fixture-app cache-failure fallback
412- run : pnpm gate fixture-fallback
450+ uses : ./.github/actions/run-gate
451+ with : { gate: fixture-fallback }
413452 # The trusted-artifact contract the device lanes rely on to decide a cached fixture
414453 # app is the one this commit expects. A real test file that no workflow ran.
415454 - name : Check the trusted fixture-artifact contract
416- run : pnpm gate fixture-cache
455+ uses : ./.github/actions/run-gate
456+ with : { gate: fixture-cache }
417457
418458 web-smoke :
419459 name : Web Platform Smoke
@@ -431,9 +471,11 @@ jobs:
431471 node-version : ' 24.13'
432472
433473 - name : Run live web smoke
434- run : |
435- pnpm clean:daemon
436- pnpm gate web-smoke
474+ run : pnpm clean:daemon
475+
476+ - name : Execute live web smoke
477+ uses : ./.github/actions/run-gate
478+ with : { gate: web-smoke }
437479
438480 - name : Upload web smoke artifacts
439481 if : always()
0 commit comments