Settings exports merge line by line: no schema_hash line, a stamp entry per source
Part of #21946 (deconflicting generated files). Two settings PRs could never merge, because each one rewrote two single lines: the source stamp schemas/settings-export/settings-schema.sources.sha256, which conflicted in 14 open PRs, and the schema_hash line of settings-schema.json, which was the whole conflict in 9 of the 12 PRs that conflict on that file.
What changes
settings-schema.jsonno longer commitsschema_hash. The Rust owner (cmux-config) computes it when the schema loads, as SHA-256 of the compact rows JSON.settings.schema, the config snapshot and the editor JSON Schema still report it. It was only ever an opaque version id, and no client compares it with a Swift-computed value; the Swift page provider already sends"".- The stamp is now one
sha256 pathentry per CmuxNextSettings source and per export test, with a blank line between entries. PRs that edit different sources then change lines that git merges cleanly, and the merged stamp is exactly the stamp of the merged sources.check-freshnow names the files that moved instead of printing two digest prefixes. SettingsSchemaExportTestswrites that format, anddefaults_guard.pycomputes it without a Swift build. The defaults approval guard still reads each PR's committed schema, and no workflow files change.
Tests (failing commit first)
tests/test_defaults_guard.pySettingsExportStampTests: a fresh manifest passes; an edited, added or removed source fails and is named; an old one-digest stamp fails; two branches that edit different sources merge with plaingit mergeinto a stamp thatcheck-freshaccepts;--refbehaves like a checkout.cmux-config/tests/schema_hash.rs: a document withoutschema_hashparses, the hash moves with the rows and only with the rows, and the committed export has no hash.
Verified on Linux: cargo test/clippy -D warnings/fmt for cmux-config, all 28 guard tests, vp check, and the webviews settings tests (129 pass). I couldn't build Swift here, so Mac CI (action exports) is the compile and export check for the two Swift files. If the export bot rewrites the stamp, it should produce byte-for-byte what the guard computes.
After merge: each open settings PR gets one last stamp conflict, which the autofix bot or the fleet export resolves. After that, settings PRs that touch different files merge cleanly.
Red, then green: at the test commit, tests/test_defaults_guard.py fails 5 of 28 and cargo test -p cmux-config --test schema_hash fails 3 of 3. At the head, 28/28 and 3/3 pass. After merging the current base, defaults_guard.py check-stamp passes on the regenerated stamp. cmux-tui-core needs the ghostty submodule, so CI runs its config tests.
Limit: two settings PRs that both edit the same source file still conflict on that file's stamp entry. The most common case is CmuxNextSettings/Localizable.xcstrings. On the 14 PRs that conflicted on the stamp, only 2 changed a source file the base also changed.
Stale exports after a merge (coord-2 review). A stamp that merges by line matches the merged sources, while settings-schema.json and docs/mdm (cmux-generated-v1) keep one side's copy. So check-fresh would have called stale exports fresh. The stamp now takes the same driver:
- Clones with the repo's drivers (the bots, a lane's local merge): merging two settings branches keeps one stamp, and
check-freshfails and names the other side's sources until the exports are regenerated.next_batchrebuilds the stamp along with the other Swift exports. - GitHub: it ignores drivers, so PRs still merge there by line. Afterwards the base autofix regenerates the exports, as it does on every push that changes CmuxNextSettings.
- Rejected alternative: embedding a hash of the stamp in the exports would bring back a single line that every settings PR changes.
- Tests:
test_a_clone_with_the_merge_drivers_keeps_one_stamp_so_check_fresh_failswas committed red first (check-fresh returned 0 on stale exports) and is green at the head. Guard tests 29/29 andtest_install_git_hooks.pypass.
Changelog
none
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Makes settings PRs mergeable (part of #21946): settings-schema.json no longer commits schema_hash, and the source stamp is now one sha256 path entry per CmuxNextSettings source and export test, so PRs editing different sources merge cleanly on GitHub.
cmux-configcomputesschema_hashat load as SHA-256 of the rows, so consumers like the config snapshot and editor JSON Schema still get one.check-freshnames the files that moved instead of printing two digest prefixes and rejects a legacy one-digest stamp; new tests cover edited, added and removed sources, legacy stamps, andgit mergeof branches touching different files.- The stamp takes the
cmux-generated-v1merge driver: a merge in a configured clone keeps one stamp and failscheck-freshuntil exports regenerate, instead of a line-merged stamp calling the one-side exports fresh. GitHub ignores drivers, so PRs still merge there by line and the base autofix regenerates the exports. - The merged base's exports and schema are current, including its rows and the dropped hash line.
After this lands, each open settings PR needs one last stamp conflict resolution; afterwards settings PRs touching different files merge cleanly. A stamp that still conflicts after a merge should be regenerated, never hand-merged.