cmux-next: a pull request carries only the generated files it caused
The PR autofix now pushes only what a pull request owns, and a new generated drift check fails a PR that carries a generated file it didn't cause. Part of #21946.
Leo's question was why we keep hitting reds and conflicts in generated files. Most of them come from the bots: the PR autofix formatted base files and regenerated exports against a newer base, then committed all of it into whichever PR it was repairing. Those copies conflicted with every other PR, and a later merge could silently drop the base's newer rows. The click-through lane saw both on #21729 and #21272: CmuxNextChromiumWarmup vanished from ci-target-graph.json, and vp fmt rewrote replyHref.ts and links.ts.
Change
scripts/cmux-next/generated_outputs.py is a table that maps each committed generated output to the inputs it's made from.
- Autofix push.
pr-autofix-apply.sh --changed FILEkeeps the PR's own files and the outputs whose inputs the PR changed. Everything else is left out with adropped:line. The push job reads the PR's changed files from the files API, not from the artifact. generated driftjob. A Linux job incmux-next-pr-autofix.ymlruns the base's copy of the table on the files API's list. It fails with an::error::per file, naming the generator and the fix:git checkout origin/feat-cmux-next -- PATH. The base autofix regenerates every output after each merge. Thegenerated-drift-oklabel skips the check.
Measured on all 259 open PRs (diff against merge base)
- The first version of the table flagged 10 PRs. Checking them found two false positives:
- With those fixes the check flags 2 PRs: #21160 (
schemas/defaults/cmux-next.jsonwith no Swift change) and #22004 (ci-target-graph.jsonwith noPackage.swiftor test change). - Limit: a PR that touches any CmuxNext test file still gets its graph copy treated as its own. The next PR makes the graph CI output, which removes this case.
Verification
scripts/cmux-next/tests/generated-ownership.test.shwas committed red first: the module and the--changedoption didn't exist. It passes at the head. It's registered incmux-next.ymlnext topr-autofix.test.sh.pr-autofix.test.shpasses, and actionlint is clean on both workflows.
Workflow files change here. Leo waived Lawrence's code-owner sign-off for the deconflict work, and Lawrence's coordinator was told.
Changelog
none
š¤ Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Pull requests now carry only the generated files their own changes caused: the PR autofix push leaves out repairs of files the PR did not change or outputs whose inputs it did not change, and a new generated drift job fails a PR that changes a generated output without its inputs.
Ownership
scripts/cmux-next/generated_outputs.pymaps each committed generated output to the inputs it is made from, covering every output kind the autofix may push, including Java SDK sources and the namespace ratchet.- The push reports each left-out path with a
dropped:line, and the autofix commit lists the files it actually pushes. generated driftruns the base's copy of the table on the files API's list and fails per file with the fix (git checkout origin/feat-cmux-next -- PATH); thegenerated-drift-oklabel skips the check from the next push.- A PR that touches any CmuxNext test file still counts as causing the graph; the next PR makes the graph CI output, which removes this case.
Measured