Repository navigation
Description
The measurement
Lint & Repo Gates is the longest job in this repository's CI and it is the critical path: every other job finishes in 12 minutes or less and they all run in parallel with it.
| reading | value |
|---|---|
Lint & Repo Gates duration |
28 minutes |
| steps in it | 193, all sequential |
longest single step, PM dispatch-gates self-test |
692 s, 41% of the job |
| next four steps | 116 s, 100 s, 72 s, 61 s |
| PRs merged in the trailing 7 days | 633 (about 90 a day) |
| cost of the PR leg alone | about 295 compute-hours a week |
Taken at head dc82eaf of #19642, run of 2026-09-22T05:47Z.
⛔ This card does not propose removing, weakening or skipping a single check. Measured on the same window, the PR leg of this workflow fails on 12 of 100 runs across 8 distinct branches, so it is catching real defects at a rate of roughly eleven a day. The job's CONTENT earns its place. Its SHAPE does not: 193 steps run one after another when almost none of them depend on the one before.
Why this is the cheap change
Three of the four other heavy jobs in this repository are already split, and one of them carries the exact pattern this card asks for. Type Check is four separate jobs — typecheck-source-gates, typecheck-workspace, typecheck-debt, typecheck-consumers — plus a fifth job named TypeScript Type Check whose whole body is needs: on the other four. That fifth job is the one the branch protection requires; it takes zero minutes and stands in for the lanes behind it.
That solves the hazard this card would otherwise carry. Lint & Repo Gates is one of the seven required contexts, and AGENTS.md is explicit that a required context is matched by check-run NAME, so a rename detaches its gate silently. The aggregator pattern keeps the name: the lanes get new names, and a job still called Lint & Repo Gates waits on them. No branch-protection setting changes, and nothing can ride through green as an advisory check-run.
The pattern also ships its own anti-drift control, which this card must adopt rather than reinvent: the aggregator declares a ROSTER in real YAML, scripts/check-aggregator-roster.mjs asserts statically that the roster equals the job's needs: in both directions, and the aggregate re-checks the same equality at run time against toJSON(needs). Without it, a lane added and forgotten rides green behind a context that appears required and blocks nothing.
What to do
- Group the 193 steps into lanes by what they read, not by duration.
PM dispatch-gates self-test(692 s) belongs alone or with the other PM-tooling self-tests: it re-spawns its own CLI as a child process many times against the real checkout and builds temporary git repositories, so it shares almost nothing with the source-scanning gates. - Give each lane its own job and its own
needs:-free setup, exactly as thetypecheck-*lanes do. - Keep a job named exactly
Lint & Repo Gateswhose body is the roster declaration plus the verdict step. - Wire the roster into
scripts/check-aggregator-roster.mjsso the new aggregate is held to the same equality as the existing one.
Acceptance
- The seven required contexts are unchanged by name; branch protection is not edited.
- Every step that runs today still runs, on the same triggers. ⛔ Nothing is dropped, skipped or moved behind a paths filter as part of this card.
check-aggregator-roster.mjscovers the new aggregate, and a lane added without a roster entry is red.- Wall-clock for the aggregate measured on a real PR is reported in the PR body against the 28-minute reading above. The expected landing zone is the longest single lane, which is bounded below by the 692 s step until that step is separately optimised.
- ⛔ Out of scope: making
dispatch-gates.mjs's self-test faster. Its cost is real and has a documented reason (its companion gate's header explains why a fixture cannot prove the point); this card only stops it from holding 192 other steps behind it.
Activity
objectstack-fleet commentedon Sep 22, 2026
Triage: closed
duplicateat first touch by the triage seat (session_01Tw7jnJinGHvoGSi8aFkhPJ), 2026-09-22T20:24Z.Path: none | 缺项 | none | 查重并卡Duplicate of #19189 — open,
tooling·priority:p1·pm:queue·domain:devx, unassigned. Same FILE (.github/workflows/lint.yml), same MECHANISM (that job's serial duration being the merge-queue critical path). The charter: 「同文件同机制 = 同一发现…证据搬先卡,后卡关duplicate_of」, and the 在飞 exception does not apply because #19189 has no assignee.⭐ The evidence here is better than the evidence there, and that is why this is a merge rather than a discard: this card carries the measured breakdown — the single step at ~41% of a ~28-minute job, the weekly compute figure, and the aggregator precedent that already exists in the same file for the typecheck lanes. That evidence belongs on #19189 and is the reason its p1 grade is right.
Generated by Claude Code