Skip to content

CI: ci.yml does not run on a push to main, so main goes red and stays red (twice by the same boot.rs doc link) #1986

Description

@macanderson

Problem

main's required fmt + clippy + test job has been failing for five
consecutive merges
(2a142b26 #1951, dcb9859b #1952, 1bdf2daf #1953,
b5ab7f84 #1955, 43402ae4 #1965). Because a red main is inherited by every
branch, every open PR shows a red gate that is not its own — which trains
reviewers to ignore the signal, and hides the PR's real failures underneath.

The mechanism is stated in #1927's own description and has not been addressed:

ci.yml does not run on a push to main.

So a PR can be green at review time and still red main on merge, and nothing
re-runs to notice. With enforce_admins and auto-merge in play, the window is
routinely exercised rather than theoretical.

Evidence that this recurs, not just happens

crates/stella-cli/src/daemon/boot.rs's module doc has broken main's
rustdoc twice within two days, by the same mechanism
:

  1. fix(stella-cli): stop a parked run stalling the whole boot resume sweep (#1698) #1920 left [`supervised::APPROVAL_REQUEST`] unresolvable → fixed by
    fix(stella-cli): unbreak main — resolve the boot.rs doc link #1920 left dangling #1927, whose title is literally "unbreak main — resolve the boot.rs doc link
    fix(stella-cli): stop a parked run stalling the whole boot resume sweep (#1698) #1920 left dangling".
  2. fix(stella-cli): resume a crash that recorded an error at boot (#1696) #1939 left [`SkipReason::NoResumePoint`] unresolvable → fixed by
    PR fix(stella-pipeline,stella-cli): unbreak main — clippy arg count and a dangling boot.rs doc link #1985.

Both are rustdoc::broken_intra_doc_links in the same file's //! block. Both
merged green as PRs. Neither was caught until a later, unrelated PR paid for
it.

The current pile-up has four independent errors from three PRs:

Error Introduced by Fixed by
plan_stage 8 args (clippy::too_many_arguments) #1953 PR #1985
[SkipReason::NoResumePoint] unresolved (rustdoc) #1939 PR #1985
PassingShell / shell_call_result undefined #1945 (test file without its helpers) PR #1964
ModelCallRole::Research match arm missing #1953 PR #1964

Note #1945: it merged a new test file whose helpers were in a different PR.
A green PR check could not have caught that either, because the helpers existed
on that PR's branch.

Files

  • .github/workflows/ci.yml — the trigger block; today it runs on
    pull_request (and ignores docs/**, *.md).
  • AGENTS.md § "The gate — run before every push" — documents the three-workflow
    split and would need updating with whatever lands.
  • .githooks/pre-push — the advisory local gate, currently the only thing that
    runs the full suite for a direct push.

Suggested direction (not prescriptive)

Add a push: branches: [main] trigger to ci.yml's required job so a broken
main is visible within minutes of the merge that caused it, and decide what
should happen when it fires (issue, revert, or just a red badge). Consider
whether docs-guards.yml and wire-schema.yml need the same, since the
paths-ignore split means each covers what the others do not.

Weigh the cost: main merges are frequent, and the job is ~10 minutes of
runner time each. A cheaper variant is a scheduled run plus a
merge_group/post-merge check.

Verify

  1. gh run list --branch main --workflow ci.yml --limit 10 — today every recent
    entry is failure, and no run is triggered by the merge commits themselves.
  2. After the change, merge something to main and confirm a run appears for the
    merge commit within a minute.

Done when

A merge to main triggers the required CI job on the merge commit, main's
status is observable without opening a PR, and AGENTS.md describes the trigger
matrix accurately.

Constraints

  • AGENTS.md's gate-parity guard (scripts/check-gate-parity.sh) fails if the
    documented gate stops matching GATE_STEPS; update prose in the same PR.
  • Workflow actions must stay pinned to commit SHAs (action-pins guard).

Noticed while repairing PR #1962's CI. Refs #1927, #1945, #1953, #1939.

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageUntyped request — convert by adding bug / feature / epic

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions