cmux-next settings exports: a fleet run hands back every export in one patch (.patch OUT)

Merged
TE
12d ago
+135-3

Lanes whose PR changes CmuxNextSettings sources can't get their settings exports back from the fleet. On pull_request events the PR autofix only uploads a patch; it doesn't push.

Cause. cmux-ci run --class light --script scripts/cmux-next/regenerate-settings-exports.sh --arg=OUT returns one --artifact file per step, and only when the step passes. So each run handed back one docs/mdm file. Two outputs had no generator in the script at all:

  • the docs settings reference, web/data/next-docs/settings-reference.generated.json;
  • the defaults snapshot, schemas/defaults/cmux-next.json.

The check-stamp failure in the #24923 runs (steps 0b46a195…, c560a395…, 38c4f70e…) had a separate cause: SettingsSchemaExportTests.exportIsFresh threw before it wrote the schema and stamp. That tree's base predated #25009 and had tabs.newTabWidgets.* without catalog keys or an agent policy. A fresh base merge fixes that part.

Fix. An OUT that ends in .patch is a bundle. The controller (validateRegenerateExportsStep) takes exactly one relative OUT, so the mode is carried by OUT itself, not by a new arg or env var. After the stamp check passes, the script:

  • writes the settings reference with a new export-next-docs.ts --settings mode (bun, or Node 22.18+), so the format still has one source;
  • writes the defaults snapshot with defaults_guard.py snapshot;
  • writes OUT as one git diff --binary patch of every regenerated file against the step's commit.

A stale stamp writes no bundle. A folder OUT, which is what the PR autofix, the base autofix and cmux-next.yml pass, behaves exactly as before.

cmux-ci run --class light --script scripts/cmux-next/regenerate-settings-exports.sh \
  --arg=settings-exports.patch --artifact settings-exports.patch --ref <sha> --key <key>
cmux-ci artifact <step id> settings-exports.patch

Routing. This step can't run on Linux because the CmuxNext package needs the macOS SDK. It runs on owned Macs through the controller (light class), and Blacksmith is never involved.

Not changed. No workflow, permission, pull_request_target or workflow_run change. The snapshot stays bot-only (#21946); the script header says to drop it before committing, as pr-autofix-apply.sh does.

Tests. tests/test_cmux_next_pr_autofix_settings.py (already registered) runs the real script in a temp repo with swift and bun stubbed. It checks three cases:

  • the bundle holds all 9 files and applies with git apply --index;
  • a folder OUT writes nothing new;
  • a stale stamp writes no bundle.

tests/test_cmux_next_base_autofix_finishes.py still passes.

Risk. Low. The new branch runs only for a .patch OUT, which no bot passes. The worker runs only the copy reviewed on feat-cmux-next, so the fleet uses this mode only after it lands.

Note: base's settings-reference.generated.json is already stale against base's schema (+63 lines). Nothing regenerates it automatically, so a bundle made on any tree will carry that drift too.

Agent session: cosmic-gray

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.