Commit 465bfce
ci: cut the Lint & Type Check critical path - split the 45-step serial job into four parallel lanes behind a name-preserving aggregator (#10484)
* ci: split the serial TypeScript Type Check job into four parallel lanes
The Lint & Type Check workflow is the merge queue's global long pole: every
candidate waits for it, so its wall clock IS the queue's per-candidate cost.
Measured on real queue builds 2026-08-20 (runs 32427686961 / 32428033244 /
32428961050): 17.9 / 17.8 / 17.1 min, against ~6 min for its sibling job.
`TypeScript Type Check` was 45 steps run strictly serially. This splits the
work into four independent lanes and keeps the required context name on an
aggregator job that `needs:` them, so the merge-queue ruleset sees exactly the
same context and no admin-side ruleset edit is required:
typecheck-source-gates the ~78s of gates that read src/ and need no build
typecheck-workspace build + turbo run typecheck (also saves the cache)
typecheck-debt build + the DEBT/TEST_DEBT ledger re-measure
typecheck-consumers build + the post-build gates that read built dist/
No gate is softened, skipped, downgraded or made non-required: every `run:` is
byte-identical to what it was, in the same relative order, and both
order-dependent pairs (authorable-surface before docs; the ledgered-closure
build before the re-measure) stayed inside one lane.
The turbo cache namespace is pinned to the literal `typecheck` instead of
`${{ github.job }}`. With the split those two spellings no longer agree, and
the expression would have given each lane its own never-written namespace --
every seed main writes unreachable, silently, with the run still green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019T1sSZbQTnLhrK9HhNdNiB
* ci: give the consumer-gate lane the nested build it used to inherit
The bare `./packages/*` glob matches only direct children, so the nested
groups (packages/plugins/*, packages/services/*, packages/drivers/*, …) reach
"Build workspace packages" only through `./examples/*^...` — whatever the
showcase happens to import. Measured with turbo's own dry-run on this tree:
that step builds 68 packages, `--filter=./packages/* --filter=./packages/*/*`
builds 74, and the 8 it adds include @objectstack/downstream-contract and
@objectstack/studio.
In the old 45-step serial job the post-build consumer gates inherited the
wider build for free — it ran earlier in the same job for the debt ledger's
sake. Splitting the ledger into its own lane takes that inheritance away, so
the consumer lane now asks for it explicitly. Without this the gates there
would resolve through a dist/ missing exactly those 8: a build-dependent gate
reading nothing and reporting "measured and clean" (#4690).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019T1sSZbQTnLhrK9HhNdNiB
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 25b7939 commit 465bfce
1 file changed
Lines changed: 594 additions & 13 deletions
0 commit comments