base autofix: make the action exports on the newest tip (base red: no action export since 02:14Z)

Merged
TE
17d ago
+639-43

Base red: ActionSurfaceParityTests.reportIsFresh (stale plans/cmux-next/action-surfaces.json and actions.md). No action export has landed since 02:14Z on 2026-10-21. Reported by omnibox-auto-2.

Why. After #23352 the Mac exports job gets a runner and finishes green, but base-autofix-push.sh judged the action exports from the run's own commit. The job queues for up to half an hour, and the actions area moves every few minutes, so every run held them:

  • run 39607727081: "newer commits changed these or their inputs" (#21921 wrote action-surfaces.json);
  • run 39609533631: "already holds the repairs that could land; left to the next run".

The settings exports already had a "made at the newest tip" path (#23249, #23315). The action exports did not.

Fix

  • New scripts/cmux-next/base-autofix-action-exports.sh (the Mac step):
    • when the actions area moved while the job queued, it checks out the newest tip and builds there first;
    • after each regeneration it reads the tip again, and regenerates on the new tip while the area keeps moving (3 times in all);
    • it prints made at: SHA, hands on the export files that differ from the run's commit, and leaves the checkout at the run's commit (prepared again) for the settings step.
  • base-autofix-push.sh judges the action exports from ACTIONS_MADE_AT, as it judges the settings exports:
    • they land whole, as made there, when nothing after that commit moved the actions area or wrote one of them;
    • a made-at commit that isn't between the base and the tip holds them, with an error.
  • Narrower holds. An action export's inputs are the actions area only, so moves in the shortcuts and app-host areas (for example first-party-apps/ or the docs-shortcuts exporter) no longer hold the exports. They still hold the files built from them, and a held export still holds what is built from it.
  • Files built from the exports, made again on the tip. This covers `web/data/cmux-shortcuts.generated.json` (the "keyboard-shortcuts docs freshness" base red), the app-host generated files and `schemas/defaults/cmux-next.json`.
    • They are built at the run's commit, so a CmuxNextActions move during the run holds them at the first push even when the exports made after that move land.
    • `base-autofix-land.sh` now remakes them in its round on the tip when the tip's action exports are known current: none was held, and nothing after `ACTIONS_MADE_AT` moved their inputs (the exports this run just landed don't count as a move).
    • The snapshot also needs the tip's settings stamp to be current (`defaults_guard.py check-stamp`).
    • `base-autofix-repair.sh` builds them from the tip's committed exports when it is told they are current.
  • Wiring. base-autofix-land.sh passes the made-at commit to the push. The workflow gives the step a 40-minute timeout and the Mac job 90 minutes, since it can now regenerate up to three times for actions and three for settings.

Tests. 16d638cabe3 is the red commit:

  • new scripts/cmux-next/tests/base-autofix-action-exports.test.sh, wired into cmux-next.yml:
    • push cases: the #21921 pattern lands; a move after made-at holds; a newer write holds the whole export; an unproven made-at holds; exports land whole; a shortcuts-exporter move does not hold them;
    • land.sh passes the made-at commit on;
    • Mac-step cases: unmoved; moved while queued (one build, on the tip, prepared, checkout restored); moved once; moved elsewhere; always moving (fails after 3, hands on nothing); a failed regeneration;
  • tests/test_cmux_next_base_autofix_finishes.py: workflow wiring. The Greptile #22474 case (a shortcuts file never lands without its export) now uses an actions-only input, and a new case checks that an app-host input change lands the export together with its shortcuts file.

Red on 16d638cabe3 (base code):

bash scripts/cmux-next/tests/base-autofix-action-exports.test.sh  # FAIL: action exports made at the moved tip did not land
python3 tests/test_cmux_next_base_autofix_finishes.py             # FAILED (failures=1)

Second red commit: b6bde599883. Cases 8 to 11 cover the files built from the exports on the tip; case 18 covers a failed checkout of the tip, which a review found was ignored under `||` and is fixed in 8edd4eb1885. Case 8 fails when run against the 7f7c5bff52b scripts.

Green on 8edd4eb1885: both pass, and base-autofix-push.test.sh, base-autofix-land.test.sh, base-autofix.test.sh, test_cmux_next_pr_autofix_settings.py and test_ci_session_label_routing.py still pass. actionlint is clean and the prepush gate reports no new violations.

Observed / Not run

  • Observed: the commands above, red then green, on huge-blue. The run ids and hold messages come from omnibox-auto-2's report; I read the push script's hold paths against them.
  • Not run: a real feat-cmux-next Mac run of the new step (the first run after merge; I'll report the first run that lands the action exports), and shellcheck (not installed here). The remade shortcuts, app-host files and snapshot on the tip are covered only by the stand-in repair in the tests; the real bun generators run on CI only.

Changelog

none

Agent session: huge-blue

🤖 Generated with Claude Code