GitHub's releases page sorts a day's tags as text, so v2026.10.15.9 showed
above v2026.10.15.18 (reported by rdbt on Discord). Tags now count .01, .02...
Every reader (release_train.tag_key, the launcher's compare_versions) compares
the parts as integers, so older unpadded tags still order correctly.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- First run (and when CONSENT_VERSION changes): a question over the launcher
with four switches, all off, what each sends in plain words, what is never
sent, "View what would be sent" (the exact JSON), and "Send nothing" /
"Save choices".
- Settings → Data collection: the same switches any time, the install ID and
what waits, "View what would be sent" and "Delete my data" (server deletion,
outbox cleared, new install ID).
- The outbox is sent at start and on close (at most 3 s), only when there is a
server (none yet) and only what the player allows.
- CLI `horizon-launcher data status|allow|deny|show|delete|send|bug|benchmark`
and MCP tools data_collection, set_data_collection, data_preview,
delete_my_data, report_bug. Bug reports and benchmark uploads are printed for
the player to confirm; logs are scrubbed and lose chat lines.
- horizon-telemetry joins the launcher's paths (launcher.yml, release_train,
pr_ready).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ludovic wants releases as often as changes land. A kind now releases when
player-facing pull requests merged since its last release and the newest of
them merged 15 minutes ago (a burst of merges becomes one release), or the
oldest an hour ago when merges never pause; release-now still ships at once.
There is no minimum time between releases. The scheduled checks run every 10
minutes (game at :02, launcher at :07) so a settled release goes out without
another merge.
Release titles keep proper nouns (Horizon's mark, Microsoft, LAN, ...) when
they lowercase the clauses after the first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Today's main would have been titled "Controllers, controllers, controllers and 17 more changes".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
release.yml now releases the game by itself: after every green checks run of a push to main, every hour
(a release the cooldown held goes out without another merge) and by hand. tools/release_train.py decides
from the pull requests merged since the last published game release: a release when one changed what
players run and the last release is 3 hours old, at once for a pull request labelled release-now;
skip-release pull requests don't count. RELEASES_PAUSED=1 stops it. Tags vYYYY.MM.DD, then .1, .2 the
same UTC day.
Linux (ubuntu-22.04) and Windows build on GitHub with Cargo caches, macOS on the Mac mini's runner
(MAC_RUNNER=macos-latest sends it to GitHub). Each builds horizon-client, horizon-ctl and horizon-prepare
(all three named: --bin selects only the named binaries), checks all three exist, checks their libraries,
starts each one, packages with xtask and archives; the Mac also runs the game offscreen for 300 frames on
a new world with resources prepared from its own Minecraft. The notes: New (label feature), Fixed (the
rest), Known issues (docs/known-issues.md). A hand-started run off main, or with dry_run, builds
everything and writes the notes but publishes nothing.
docs/release-flow.md describes the flow, the labels, pausing and rolling back; the launcher gets a test
that a release turned back into a draft is never offered.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>