(motir-core) Cut the PR lane's job fan-out — path-filter the container-image jobs, take the at-scale E2E legs off the PR trigger, and replace the branch-NAME skips with diff predicates
A ci.yml run is 37 jobs, and a large share of them cannot be affected by the diff that triggered them. Cut the fan-out so the concurrency budget buys more runs, not more jobs per run.
Three cuts
- The container-image jobs are unconditional.
sandbox(→sandbox-images.yml: smoke + matrix setup + one leg per profile inpackages/cli/sandbox/smoke/profiles.json) andrunner-image(→runner-image.yml) run on every PR. Gate them on the diff. - The at-scale E2E legs run on every PR.
board-at-scale,collab-at-scale,reporting-at-scale,billing-cloudare self-seeding, cap-parameterised lanes that regress rarely and cost a leg each. Move them to push-to-mainplus an opt-in PR label, keeping the bulk and@a11ylegs on every PR. - The skip predicate is a branch-NAME proxy for the diff. Every heavy job carries
!startsWith(github.head_ref, 'seed/'|'design/'|'docs/'). Aparent/…orsubtask/…PR that touches onlydocs/**still runs the full suite, and adocs/…branch that touches app code skips it — wrong in both directions. Replace with a predicate over the actual changed paths.
Orientation only, recount on fresh origin/main: ~10 of the 37 jobs are image builds; 4 of the 11 E2E legs are at-scale (the card first said 5, counting board-scrum-at-scale separately — it is selected within the board-at-scale leg's --grep).
Acceptance criteria
- On a PR whose diff touches none of the image inputs,
gh run view <id> --json jobslists zero jobs whose name beginsSandbox images /orRunner image /; on a PR that touches any one of them, every one of those jobs is present. On a PR carrying no opt-in label, that same job list contains no E2E leg whose id ends→ AMENDED 2026-08-19. The at-scale legs must not RUN — they may still appear as a greyed-at-scale, and none namedbilling-cloudSkippedcheck. Evidence (rung 2,ci.yml's own comment above the acceptance-video note, present before this card): "A matrix leg cannot be dropped by an expression, and a job-levelif:only downgrades the check to a greyedSkipped; an untriggered workflow is the only thing that leaves nothing behind." Making them genuinely absent means a separatepaths:-filtered workflow, which would take them out from behindCI completeand downgrade a merge gate. A skipped job consumes no runner, so the entire saving is realised either way. Same amendment applies to the caller jobs in AC 1 — their nested jobs (Sandbox images / …) are genuinely absent, the callers themselves reportSkipped. The same query on the following push-to-mainrun must contain all of them.A grep of→ AMENDED 2026-08-19. No job's code contains.github/workflows/ci.ymlforgithub.head_refreturns nothingstartsWith(github.head_ref— i.e. nothing decides what to run from the branch name, which is what the parenthetical always said. Evidence:design-guardspassesDESIGN_PR_REF: ${{ github.head_ref }}to the design-asset uploader as metadata; that is a data use, not a gate, and removing it would break design-result publishing. Asserted as a self-recounting predicate over every job body inci-design-guards-lane.test.ts, so a new job that reintroduces a branch-name gate fails it too.CI completereports success on a PR where the jobs in AC 1 and AC 2 are absent or skipped. A job-levelif:that evaluates false still reports a check — the defect MOTIR-1958 filed against the starter's acceptance lane. (Already structurally satisfied: the gate's script treatsskippedas satisfied.)- The E2E legs that DO run on such a PR are unchanged in selection: the five bulk legs still
--grep-invertthe at-scale tags and@a11y, andtests/e2e-shard-plan.test.tsstill fails on an unmeasured new spec. No spec silently stops being covered on a PR. - Measured on one real PR after the change: total job count for a code-touching PR run is materially below 37, and for a docs-only PR is in the single digits. Record both numbers in an
add_commenton this card.
Out of scope
Anything about where jobs run (GitHub-hosted vs. the fleet) and any plan-tier change — the two sibling cards. Do not touch concurrency: on ci.yml: MOTIR-3106 settled cancel-in-progress and its reasoning still holds.