Skip to content

feat: immutable editions - #9357

Open
joseph-isaacs wants to merge 5 commits into
developfrom
claude/immutable-core-editions-e2zybh
Open

feat: immutable editions#9357
joseph-isaacs wants to merge 5 commits into
developfrom
claude/immutable-core-editions-e2zybh

Conversation

@joseph-isaacs

Copy link
Copy Markdown
Contributor

Currently there is no way to ensure editions persist apart from code review.
This pr add a CI check and also creates useful output that can be used to code-gen other docs

claude added 4 commits August 11, 2026 10:57
A frozen edition carries a read-forever guarantee, so its encoding set must
never change again. Enforcement so far was a single inline assertion pinning
core2026.07.0 -- not the edition the default writer targets -- leaving three of
five frozen core editions unpinned, and living in the same mutable tree as the
declarations it guarded.

Generate one TOML record per frozen edition, holding the identifier, the
recorded min_vortex_version, and the full computed encoding set. A test keeps
the records in step with EDITION_DECLARATIONS and rejects a record with no
frozen edition behind it, so deleting or unfreezing a declaration fails too.
Update mode never removes a file, so unfreezing cannot be laundered through the
generator.

Two CI checks close the loop. The generated-files job regenerates the records
and fails if git is dirty, alongside the existing flatbuffers and proto
generation. A new job rejects any diff that modifies, deletes, or renames a
record, and any newly added edition that is not newer than its family's newest
recorded edition.

required_vortex_release is deliberately left out of the records: it is
backfilled from compat-fixture evidence after an edition freezes, so pinning it
would put that backfill in conflict with the append-only rule.

Signed-off-by: "Joe Isaacs" <joe.isaacs@live.co.uk>
Record it in a table of its own rather than beside each encoding. It is the one
fact in a record that is not fixed at freeze time -- it is backfilled from
compat-fixture evidence as that evidence appears -- so giving it its own table
makes a backfill purely an added line.

The append-only check parses both revisions of a modified record and permits
exactly that transition: the table may gain entries, but everything else must be
byte-identical and a release that was already recorded may never change or be
dropped.

Signed-off-by: "Joe Isaacs" <joe.isaacs@live.co.uk>
Editions are drafts until a min_vortex_version is recorded, and a draft is
free to change, so recording only frozen editions left the drafts invisible.
Generate a record for every declared edition instead. A draft's record may
change, move, or go away with the draft; freezing turns the record into a
read-forever contract that never changes again.

The CI check reads frozen-ness from the record at the base revision, so a diff
cannot unfreeze an edition and edit it in the same change, and the generator
refuses to unfreeze a record it finds on disk.

Encoding ids in a declaration may now be paired with the release that first
read them -- `&("vortex.alp", "0.36.0")` -- which flows into
EditionInclusion::required_vortex_release and into the records. Each core
edition's members are recorded as requiring the release current when that
edition froze, checked against the published release timeline: 0.36.0
(2025-05-28), 0.40.0 (2025-06-26), 0.54.0 (2025-10-20), 0.84.0 (2026-08-07),
and 0.65.0 (2026-03-25) for core2026.07.0, whose only member vortex.variant
first shipped there. These are upper bounds under each edition's own immutable
min_vortex_version, so the check permits refining them as compat-fixture
evidence narrows them, but never dropping one.

Renamed the module and script from `frozen` to `records`, since they now cover
drafts too.

Signed-off-by: "Joe Isaacs" <joe.isaacs@live.co.uk>
The exporter belongs with the repo's other generated files, so move it to
`cargo run -p xtask -- generate-editions`, alongside generate-fbs and
generate-proto, and run it from the same generated-files CI job that already
checks git is clean afterwards. The `#[cfg(test)]` module and its
UPDATE_EDITION_RECORDS environment variable are gone; the two rules git history
cannot see -- a record may not be deleted, and a frozen edition may not return
to draft -- now fail the exporter itself.

Drop the per-encoding release from the records. An edition declares the release
it froze in, so repeating it on all 23 of core2025.05.0's members said nothing
that the edition did not already say. Declarations return to plain encoding
lists, EditionInclusion::required_vortex_release goes back to being unset until
there is per-encoding evidence to record, and the append-only check simplifies
to rejecting any change at all to a frozen record.

Signed-off-by: "Joe Isaacs" <joe.isaacs@live.co.uk>
@joseph-isaacs
joseph-isaacs requested a review from AdamGS August 11, 2026 13:40
@joseph-isaacs joseph-isaacs added the changelog/feature A new feature label Aug 11, 2026
@joseph-isaacs

Copy link
Copy Markdown
Contributor Author

Thoughts on using CODEOWNERS for these files?

@codspeed-hq

codspeed-hq Bot commented Aug 11, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 1962 untouched benchmarks
⏩ 89 skipped benchmarks1


Comparing claude/immutable-core-editions-e2zybh (fe888df) with develop (c4bb934)2

Open in CodSpeed

Footnotes

  1. 89 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on develop (8b4ad91) during the generation of this report, so c4bb934 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Families version independently, so a flat directory mixed two unrelated
chronologies and left the reader to spot the family from a filename prefix.
Group the records as `vortex/editions/<family>/<edition>.toml`, mirroring the
declarations in `vortex/src/editions`.

The exporter creates a directory per family and treats a record under the wrong
one as a stray, since that is what it is. The append-only check requires a newly
added record's directory to match the family its name declares, so a record
cannot be filed under a family whose chronology it does not extend.

Signed-off-by: "Joe Isaacs" <joe.isaacs@live.co.uk>
@robert3005

Copy link
Copy Markdown
Contributor

what do you want to enforce with codeowners? We can maybe require +2 for changes to these?

@robert3005

Copy link
Copy Markdown
Contributor

also before we do this we should make sure editions have all the objects we care about

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

Labels

changelog/feature A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants