You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Split Lint & Repo Gates into parallel lanes behind an aggregator, the way TypeScript Type Check already is: 193 serial steps are 28 minutes of every PR's critical path and one step is 41% of them #19686
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 the typecheck-* lanes do.
Keep a job named exactlyLint & Repo Gates whose body is the roster declaration plus the verdict step.
Wire the roster into scripts/check-aggregator-roster.mjs so 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.mjs covers 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.
Triage: closed duplicate at 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.
⚠️ ⛔ Not merged with #19687 (same file, different mechanism — the leg's catch rate). 同族异缺陷, 互链排同批.
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