Files
Nikita Maximilian GrimmandClaude Opus 5.5 2bc92b6348 Serve shader API 0.2 behind HORIZON_HDR_FRAME=float
With the switch, the game draws 0.2 packs ([frame] blend = "linear" is
still refused). A renderer made with a 0.2 pack picked draws a float frame
where the device can, else the 8-bit one; a pack picked or dropped later
runs on the frame there is, logged once. The renderer's material, sky,
weather, vertex and shadow entries decode a 0.2 stage's colours and encode
its results; scene_color, opaque_color and the water mirror are decoded
copies, shadow_color is float, and Frame's sky and fog colours are
decoded. The post chain ends in a window-size picture, and the pack's
[tonemap] (or Horizon's clip) draws it onto the frame, encoded at alpha 1.
With HDR on, HDR output lifts nothing of a 0.2 pack's world.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 15:37:14 +01:00

7.3 KiB

API stability and versioning

The rules every Horizon API follows (the APIs): how each one is versioned, what the stability levels promise, how something is deprecated and removed, and the tests that keep old mods, scripts and tools working.

Versions

  • Each API has its own version, separate from the game's release (v0.2.14, versioning.md) and from Minecraft's. A game release says which API versions it serves.
  • Semantic versioning, MAJOR.MINOR.PATCH. A line is what stays compatible: 0.1, 0.2, … before 1.0, then 1, 2, ….
    • Before 1.0: an addition makes the next patch (0.1.0 → 0.1.1); a breaking change starts the next line (0.2.0).
    • From 1.0: an addition makes the next minor (1.0 → 1.1); a breaking change starts the next major (2.0).
  • Where the version lives:
API The version A user names the line they need
Content mods the manifest's api line api = "0.2" in horizon-mod.toml
Native mods the Horizon and horizon-mixins revisions the bundle pins horizon_revision in horizon-mixin.toml
Agent control the control protocol's version (hello replies it; MCP serverInfo carries the release) horizon-ctl --api 0.1
Server control API the path (/api/v1/) the path
server.toml the file's keys; a key is never renamed in place nothing: old files keep loading
Launcher commands the command names and their --json output nothing
Data formats a version or schema field in the file the reader rejects versions newer than it knows

What counts as a breaking change

Breaking: removing or renaming anything; changing a type, a default, a unit or a meaning; making something optional required; refusing input that was accepted; a JSON field that changes type.

Not breaking: a new function, interface, capability, command, endpoint, tool or server.toml key; a new optional argument or JSON field (readers must ignore fields they don't know); faster, or fixing behaviour to what the reference already says.

Stability levels

Every part of an API has one level, shown in its reference and its surface page.

Experimental Preview Stable
Who may use it opt-in only (a flag or a manifest field naming it); never in a release default anyone; marked "preview" where players see it (a mod's row on the Mods page) anyone
May change in any release, without notice only at a new line, after a deprecation only at a new major, after a deprecation
Deprecation window none at least 30 days, with one release line serving old and new at least 180 days, with the old major served beside the new one
Needs a design note a generated reference, a guide section, an example, compatibility tests the same, plus one line of real use without a break
  • Promotion. Experimental → preview when it has what the table asks. Preview → stable when real users (a published mod, a host's script, an agent's tool) used it for a whole line and nothing broke. The maintainers' orchestrator proposes the promotion with the evidence (the compatibility tests, the complete docs, that line of use) and Ludovic approves it.
  • Horizon-only by design. An API is stable only for what Horizon itself does; a vanilla concept it exposes (a block id, a command, a server.properties key) changes when vanilla changes it, with a version port (version-ports.md), and the changelog says so.

Deprecation and removal

  1. The pull request that deprecates marks it where it is defined (a /// Deprecated: use X; goes in 0.3. doc comment, a deprecated field in a tool's schema) and adds the replacement in the same release.
  2. The reference shows it as deprecated, and the surface page's changelog says what replaces it and when it goes.
  3. Using it logs one warning per mod, session or client, naming the replacement; it keeps working.
  4. It is removed only after the window, and only at the next line (preview) or major (stable).
  5. A line or major that is no longer served is refused with a clear message (needs API 0.1; this Horizon serves 0.3 and 0.4), never loaded half-way.

Compatibility tests

Every preview and stable API has tests that run old users against the current code, in CI:

API The test
Content mods the content template builds and checks with cargo horizon-mod, and mod_content's tests load content mods; a line is served as long as they pass
Native mods hook points are only ever added, and tests keep each one hookable (tests::hook_points_stay_hookable and tests::loot_table_load_stays_hookable, game/native_hooks.rs)
Agent control a transcript per protocol version: commands and the reply keys each must have
Server api::ROUTES against route() (generated reference); a server.toml from each release line parses to the same settings; golden replies per endpoint
Launcher the generated reference; golden --json output per command
Launch the generated reference, which holds --launch-api's reply; every listed option is accepted; horizon-prepare's --progress json lines (progress_json_lines_keep_their_shape), its --launch-api reply and options (launch_api::tests, launch_api_options_are_in_the_help)
Data formats a sample file of every version a reader accepts, read by today's reader

The generated references are the API's own diff: a pull request that changes an API changes its reference, and the reviewer applies the rules above to that diff.

Changelog

Each surface page ends with a changelog: one line per change, newest first, with the API version and the pull request. Deprecations and breaking changes are in bold. The release notes of the game release that ships a change link it.

Today

Part Level Version
Content mods (registries: data-driven blocks, items, mob effects, thrown entity types and menu types) preview manifest api = "0.2"
Native mods (horizon-mixins bundles, native-mods.md) experimental the pinned revisions
cargo horizon-mod (new, build, run, check) preview none yet (unversioned)
Shader API experimental 0.1
Shader API 0.2 (linear light, hdr-linear-light.md) experimental, behind a switch: horizon-shader checks it, the game draws it only with HORIZON_HDR_FRAME=float set, and the registry doesn't list it 0.2
horizon-ctl commands and MCP tools preview none yet (unversioned)
The game's own control-socket commands outside horizon-ctl's table (test hooks) experimental
horizon-server commands, server.toml stable horizon-server --version
Server control API stable /api/v1
horizon-launcher commands and MCP tools preview none yet (unversioned)
Launch API: horizon-client's launch options, session JSON, exit codes; horizon-prepare's output and progress experimental 0.1.0, horizon-client --launch-api and horizon-prepare --launch-api
Benchmark report stable "version": 1
Telemetry batch and consent stable "schema": 1, consent 2
horizon-graphics.txt, horizon-extras.txt, horizon-mods.txt preview none
SHA256SUMS and SHA256SUMS.sig stable