Skip to content

base autofix: finish each run and land it on the newest tip - #22004

Merged
teamleaderleo merged 10 commits into
feat-cmux-nextfrom
claude/base-autofix-lands-on-moved-tip
Oct 21, 2026
Merged

teamleaderleo merged 10 commits into
feat-cmux-nextfrom
claude/base-autofix-lands-on-moved-tip

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

This moves base autofix's push step on feat-cmux-next into scripts/cmux-next/base-autofix-push.sh and tightens what it lands on a moved tip. It no longer fixes the settings-export livelock by itself (see Not fixed here).

Background: base already stops cancelling runs in progress (#22038), and it already re-applies a repair file by file when the tip has moved (#22474). When the newer tip changed any input of a repaired file, the "Push the repairs" step leaves that file out and fails the run. That is the right thing to do: an export made at the old head could be wrong at the tip (a revert in between, say). This PR keeps that rule.

What changes

  • "Push the repairs" calls scripts/cmux-next/base-autofix-push.sh. It reads the same input areas (autofix-areas.sh) and holds every file whose areas BASE..tip touched, along with any output no area is known to build. A file that comes from a moved input never lands as it was made.
  • A file is also held when a newer commit wrote it: a PR's own regeneration, or a base autofix repair made from a newer tree. An older autofix commit is overwritten instead of blocking the file, as the old rule did when the tip had edited it at all.
  • Exports land whole or not at all: the schema, docs/mdm and the stamp go together, and so do the three action exports. Strings, docs shortcuts and app-host files built from an export that waits wait with it.
  • The defaults snapshot is never copied from the old tree. It is re-made on the tip with defaults_guard.py snapshot, and only when nothing else waits.
  • If the commits since BASE can't be read (a bad fetch, say), the run stops. Before, that read as "no newer writes".
  • A push that is refused while the branch didn't move fails at once. A lost race is retried up to CMUX_BASE_AUTOFIX_PUSH_ATTEMPTS times (5). If the tip already has the repair, nothing is pushed.
  • The script is in the workflow's push paths, and its test runs in cmux-next.yml.

Not fixed here: the settings inputs include CmuxNextSettings/Localizable.xcstrings, which changes with almost every merge, and the Mac export plus autofix take about 18 minutes. So most runs still hold the settings exports, as on base (for example, run 39553409406 left them out after the tip moved to 3e0b1c2). The way out is to regenerate on the newest tip, or to have the settings area stop counting string-catalog-only changes. That is follow-up work.

Tests

  • python3 tests/test_cmux_next_base_autofix_finishes.py is base's suite from ci(cmux-next): base autofix lets a running repair finish and re-applies it on a moved base #22038/ci(base autofix): land the files of untouched areas when another area moved #22474, now driving the script instead of slicing the inline loop. Three of its cases were reworded:
    • Two retry cases expect attempt 2 of where the old loop reached attempt 3, because the script reads the tip before its first push.
    • The "conflict" case is now "a newer write of the file fails without pushing and names it", because the script applies no patch.
    • Every hold case is unchanged, including "a repair whose inputs changed meanwhile is left to the newer run".
    • Red against the previous head's script: 7 failures, including that inputs-moved case. Green at the head: 16 OK.
  • bash scripts/cmux-next/tests/base-autofix-push.test.sh runs in a shallow bot clone. Its cases:
    • 1–6: plain push, moved tip, a newer edit of the file, an older autofix replaced, already landed, a deleted directory.
    • 7: moved settings inputs hold the exports.
    • 8: the workflow pushes through the script.
    • 9: one file waits and the rest lands.
    • 10: exports land whole.
    • 11: an older run never overwrites a newer one.
    • 12: the snapshot is re-made on the tip.
    • 13: bounded retries.
    • 14: a rejection with no move.
    • 15: unreadable history fails closed.
    • Green at the head: "PASS: base autofix lands its repair on a moved feat-cmux-next; files whose inputs moved or that a newer commit wrote wait".

Observed / Not run

  • Observed: both suites red on the previous script, then green. actionlint on the base autofix workflow is clean. prepush-gate.py reports no new violations.
  • Not run: the new push path hasn't run on GitHub yet; the first base run after the merge is the real check. The real defaults_guard.py snapshot on a moved tip is covered only by a stand-in. shellcheck isn't installed on huge-blue.

Changelog

none

Agent session: huge-blue

🤖 Generated with Claude Code

teamleaderleo and others added 2 commits October 19, 2026 06:34
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every base-autofix run since 05:27 was cancelled by the next push (39 in a
row): the Mac export takes ten minutes or more and feat-cmux-next takes a push
every minute or two, and the push step refused any tip but the run's own. The
settings export stamp went stale and defaults-snapshot turned red on most open
pull requests.

- Neither the export job nor autofix cancels in progress; only the newest
  push waits behind a running one.
- base-autofix-push.sh replays the repair onto the newest tip when no newer
  commit wrote a file it writes, and refuses otherwise (the next run repairs).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 20e9ee60-e171-4b65-853d-d3eb8ca143b3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-q2p3h created for this PR by the cmux coordinator.

teamleaderleo and others added 2 commits October 19, 2026 06:41
…h, refuses a deleted directory

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r orphaned pushes

The next queued run checks out a tip without the previous run's replayed
repair, regenerates the same files, and was refused by that bot commit, so
every second run failed under steady pushes. Earlier base autofix commits no
longer count as newer edits; the repaired files are written onto the tip
instead of cherry-picked, an already-landed repair pushes nothing, and a file
added in a directory a newer commit removed is refused. Errors also reach
the step summary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review findings addressed in d078080, with the failing tests committed first (42dbd9e):

  • High: the next queued run checked out a tip that didn't have the previous run's replayed repair, regenerated the same files, and was refused by that bot commit. Earlier chore(next): base autofix at commits now don't count as newer edits. The script writes the repaired files onto the tip instead of cherry-picking them, and it pushes nothing when the tip already holds the repair.
  • Low: it refuses a file the repair adds in a directory that a newer commit removed.
  • Low: the script's errors now reach the step summary (2>&1).

All 6 test cases pass, and actionlint is clean.

- regenerated Packages/macOS/CmuxNext/ci-target-graph.json
- vp fmt webviews/src/agent-session/acpmux/replyHref.ts
- vp fmt webviews/src/pages/markdown/README.md
- vp fmt webviews/src/pages/markdown/links.ts
- vp fmt webviews/test/markdown-cmux-app-links.test.ts

Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39211430716
@cursor

cursor Bot commented Oct 19, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 9f1ec6a: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr22004 -f ref=claude/base-autofix-lands-on-moved-tip -f platform=macos -f backend_mode=local

Pending: CI is running on 9f1ec6a4e0 (run); the result below was for 651fdd1339 and no longer applies.

Last result: Passes: CI passes on 651fdd1339.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); it is rewritten when this head's CI completes.

web and size checks: green

CI fast guards passes on 9f1ec6a4e0 (run). This covers only the fast guards, not CI: CI's result is ci-status.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Orphaned: no activity for 14 h, and no lane holds a lease on it. The orphan sweep could not merge feat-cmux-next in: conflicts in .github/workflows/cmux-next-base-autofix.yml, webviews/src/agent-session/acpmux/replyHref.ts, webviews/src/pages/markdown/links.ts. Listed for a lane to resolve.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by land-and-ci-a8 on huge-blue · session

teamleaderleo and others added 3 commits October 21, 2026 06:45
…on-moved-tip

Conflicts: the stale PR-autofix files (replyHref.ts, markdown links, ci-target-graph.json)
take base. cmux-next-base-autofix.yml takes base's version (it already lets running jobs
finish and re-applies a repair on a moved tip); the PR's push fix is re-applied on top in the
next commit. cmux-next.yml takes base's concurrent check list plus base-autofix-push.test.sh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue
…ack only what a newer commit wrote

Red on the merged base: the workflow's Push the repairs step leaves the settings exports
to the next run whenever the tip changed CmuxNextSettings (run 39553409406), and the push
script refuses the whole repair over one newer file, lets an older run overwrite a newer
repair, and copies the defaults snapshot from the stale tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue
…of leaving it to the next run

The Push the repairs step left every repaired file whose area's inputs moved to the next
run and failed. CmuxNextSettings moves with nearly every merge and the Mac export takes
ten minutes, so the settings exports never landed (run 39553409406: pushed part, left
docs/mdm, the schema, the stamp and the snapshot). The step now calls
base-autofix-push.sh, which lands them on the moved tip: each export carries its stamp,
so what changed since is still flagged and the newer run regenerates it.

Only a file a newer commit wrote waits (a pull request's regeneration, or a repair made
from a newer tree; an older repair is replaced); an export waits whole, with the files
built from it, and the run then fails so the next run's since stays older. The defaults
snapshot is derived again on the tip. Pushes retry a bounded number of times.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue
@teamleaderleo teamleaderleo added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 21, 2026
@blacksmith-sh

This comment has been minimized.

teamleaderleo and others added 2 commits October 21, 2026 07:11
…fix-push.sh

The base suite (#22038, #22474) drove the inline push loop, which this branch
moves into scripts/cmux-next/base-autofix-push.sh; it now drives the script.
Its cases stand, including that an export whose inputs moved on the tip is
left to the newer run. The script's own suite now expects that too, and a
fail-closed read of BASE..tip and a rejection with no move.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue
…l closed on unreadable history

Keeps #22474's invariant: a file made at BASE_SHA never lands as-is when
BASE..tip touched its input areas (autofix-areas.sh), unknown outputs never
land, and the defaults snapshot never lands beside a file that waits. Failing
to read BASE..tip now stops the run instead of reading as no newer writes,
and a rejected push with no move fails at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c6d-a1d2-7fc2-9458-92c6bdcb7b4d&host=huge-blue
@cursor

cursor Bot commented Oct 21, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@teamleaderleo
teamleaderleo merged commit 85b78fe into feat-cmux-next Oct 21, 2026
@teamleaderleo
teamleaderleo deleted the claude/base-autofix-lands-on-moved-tip branch October 21, 2026 08:55
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

merge-audit: #22004 merged at 9f1ec6a without no SHIP review receipt on the head. #23227 reverts it. To keep this change, add the missing evidence for 9f1ec6a here; the next audit pass then closes #23227. Otherwise review and land #23227.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (subagent, correctness first): SHIP at 9f1ec6a

scripts/cmux-next/base-autofix-push.sh follows the hold rules in the body and fails when history can't be read. The push step runs under set -euo pipefail, so the script's exit code survives the tee. It is conservative: a newer bot repair that writes an export counts as a moved input, so more files wait than strictly need to, but nothing wrong lands. Not high-risk: it adds no trigger, credential or permission.

Agent session: huge-blue

@github-actions

Copy link
Copy Markdown
Contributor

Shipped in:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant