🤖 Agent: Merged by Ludovic's AI agent (orchestrator), crate split route (c): head 64c174118 (main merged in, no rebase) passed the full tools/pr_ready.py on the Mac mini (2327 workspace tests, 398 Python, launcher 205; parity --changed 130 run, 0 failed) plus command_exec and save_roundtrip --fresh; verify green.
Without vscreen, save_roundtrip, world_reopen and spawn_loot stopped on
FileNotFoundError, and lan_e2e's games opened windows on the real
desktop: unfocused, the host paused before its world loaded and waited
at "Connecting to the server..." until wait-ready gave up. They now run
offscreen there, as on macOS, and lan_e2e's games also skip the pause
(as HORIZON_E2E_HEADLESS does).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The repositories moved from ludovic111 to the horizon-rust organization.
GitHub redirects repository URLs but not GitHub Pages, so the mod index
moved to https://horizon-rust.github.io/horizon-mods/: the launcher and
the game read it there. The launcher still accepts icons and files from
the old addresses, which a mirror keeps serving for launchers released
before the move.
Release notes thanked ludovic111 once the repository's owner became the
organization (verify failed on main): the maintainer is now named.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: Merged by Ludovic's AI agent (orchestrator) after review: comment commands for the trusted reviewers (/close, /reopen, /label, /unlabel), from main's code only, same list and pause as /nightly.
Move-only step B6 of the horizon-client crate split. These four modules
only reached gameplay modules for small helpers, so after this they depend
only on the render/world layer and can move into its crate whole, impls
included.
- save::float moves to horizon_client_core::nbt_value (save re-exports it).
- mobs::spawner::normalize_id moves to horizon_client_core::identifier
(spawner re-exports it).
- containers::Providers moves to its own module, providers.rs
(containers re-exports it).
- vault, command_block and sculk import number/text/float, item_nbt,
Who and scoreboard from their real homes instead of through save and
mobs; brewing imports Providers from providers.
- The vault, spawner and trial_spawner harnesses record the client-core
files the moved helpers now live in.
- villager_brain's `impl Poi` (max_tickets, valid_range) moves next to
the type in poi_sections, and its two methods become pub.
No behaviour change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: Merged by Ludovic's AI agent (orchestrator). The full pr_ready ran on this exact merge with main: clippy -D warnings, 2325 workspace tests, 365 Python tests, launcher 197, and 116 affected harnesses (114 passed, 0 failed). Verify is green here. rdbtCVS approved. Crate split, priority 1.
Ludovic's decision (2026-10-27). `nightly.py prune-builds` runs in the
scheduled `pick` only, with main's code, and lists each deletion in the run
summary. It deletes only branches named nightly/build-<date>-<n> older than
7 days, never the newest build, and never one a published `nightly` or
nightly-<date> release points to. nightly-state and every other branch are
left alone. tests/test_nightly.py pins it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: Merged by Ludovic's AI agent (orchestrator). rdbtCVS's requested changes are addressed (he said on #2215 not to wait for his re-review), and this head is proven in union/cg19-r2 and union/cg19-r3 (clippy, 1722 tests, 135 + 96 harnesses, lan_e2e). Thanks @kacpherek!
🤖 Agent: playhorizon's CI runner now skips the harnesses its host entry excludes (remote_fireball, remote_fireworks fail there on bare main from CPU starvation); pr_ready clean, unit test added.
Orchestrator's review of #2859: a nightly can hold pull requests nobody
reviewed yet, and their build scripts run in `build`. game-build.yml gets a
`trusted` input, true only from release.yml:
- the Rust cache (GitHub-hosted Linux and Windows): its own key for an
untrusted build (`nightly-<name>`), never saved; a release restores only
what a release saved;
- macOS: an untrusted build's exporters and build jobs run on the runner
that already runs pull requests' parity jobs (macOS + horizon-game), never
the release runner (MAC_RUNNER) nor parity-main's;
- a trusted build doesn't read the machine's shared sccache, which pull
requests' jobs write (runner-env.sh: HORIZON_NO_SCCACHE).
tests/test_nightly.py pins all three.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Step A of the horizon-client crate split. `Chunk.block_entities` held
`containers::BlockEntity`, whose payloads were defined across containers,
brewing, signs, sculk, mobs::spawner, mobs::trial_spawner, vault, beehive
and command_block, so `chunk` reached most of the gameplay code.
The enum and every payload type now live in `chunk/block_entity.rs` as
plain data (definitions and derives). Every impl block stays in its
feature module, and each module re-exports its types under the old path,
so callers don't change. Also:
- `mobs::Who` moves to `horizon_client_core::who` (the vibration `Info`
names it); mobs re-exports it.
- `skins::NameOrId` moves beside `SkullSkin`, which holds it; skins
re-exports it.
- `Spawner.next`, the `Next` enum and `Selector.current` become
`pub(crate)`, since their struct now lives in another module.
- The vault, spawner and trial_spawner harnesses record
`chunk/block_entity.rs`.
No behaviour change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ludovic's decision (2026-10-27, from kacpherek's proposal under #2779): the
Nightly is where contributors test pull requests before the gate.
kacpherek, rdbtCVS and levzzz5154 (.github/nightly-reviewers.txt) and
Ludovic pick them with `/nightly 2640 2642`, `add`, `remove`, `clear`,
`status` or `dry-run` in any issue or pull request.
- nightly-command.yml (issue_comment, main's copy): checks who asked, saves
the set on nightly-state, starts `nightly build`, answers "🤖 Nightly: …".
It never checks out or merges a pull request.
- nightly-build.yml: `pick` builds main + the set (newest heads and merged or
closed ones dropped at the scheduled run), pushes it as
nightly/build-<date>-<n>, records it in builds.jsonl; build, sign and
publish are unchanged; `answer` tells the thread how it ended.
- Notes say a Nightly can include pull requests not reviewed yet, picked by
trusted reviewers, and list each with its author and who picked it.
- docs/release-flow.md: who can pick, how, how Ludovic removes or pauses them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pieces of nightly-2 (`/nightly 2640 2642`): parsing a comment, the
reviewers list (.github/nightly-reviewers.txt, with a `paused` line), the
refusals (paths CODEOWNERS gives to Ludovic, closed or merged PRs, more than
30, more than 6 builds a day), the set and its commands (Ludovic's remove
keeps reviewers from adding a PR back), the nightly-state branch (pushed with
retries when another run saved first), and the assembly: each PR head merged
onto main in order with `git merge-tree --write-tree`, objects only, so no
file, hook or filter of a pull request reaches the runner. Equal inputs give
the same commit. A conflict names the two pull requests (or main) and the
paths.
Nothing calls it yet: the next PR wires it into nightly-build.yml and a
`nightly command` workflow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
playhorizon's runner fails remote_fireball and remote_fireworks even alone and
at bare main (3b19c386c: 2 of 2 runs and the retry), while the Mac mini passes
them; every fork PR whose parity lands there stopped on them. The host's
exclude list only kept harnesses off workers sent there, not off the runner's
own jobs: platform_skips now adds the local host's exclude, skipped with its
reason unless named. The two harnesses join playhorizon's list; the Mac
mini's runner and the nightly audit (macOS) keep running them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The harness hashed crates/horizon-client/src/{mouse,window,keymapping}.rs,
which this branch moves to horizon-client-input, so CI's parity job failed
with FileNotFoundError before running it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nightly-build.yml builds, once a night, the newest union/<agent>-<name> branch on origin when it is newer than
main and holds something main lacks (else main), and publishes it as the `nightly` pre-release; the previous one
stays a week as nightly-<date> (tools/ci/nightly.py pick/rotate/prune). Launchers ignore it until a player turns
Nightly on (next PR).
The release builds move unchanged into game-build.yml, a reusable workflow both release.yml and the nightly call
from main's copy. The nightly builds with no secrets and the macOS keychain locked; only the sign job holds the
key, and it runs nothing but main's sign_release.sh over the archives, for the message "horizon release nightly".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: Merged by hand by Ludovic's AI agent (orchestrator) after the contribution gate. rdbtCVS's change request is addressed at this head; a re-review was asked, with no new objection since. Proven in wave 5's union run (cg20 union C 5900ab38793aa602315091ab4873615e93dda57d (main b6f18dc8f + 57 PRs) Mac mini 122/122 delta harness).
🤖 Agent: Merged by hand by Ludovic's AI agent (orchestrator) after the contribution gate. rdbtCVS's change request is addressed at this head (checked against the head by contrib-gate-20). Re-review was asked about 07:30Z with no new objection. Proven in wave 5's union run (main + 54 PRs, 332/332 selected harnesses; lan_e2e 18/18 in-frame and on the server thread). Thank you!
sprites.rs called back into gfx for this one function, one of the edges that
keep the client lib's modules in a single cycle. The function and its test
move to sprites.rs; gfx calls it there. No behaviour change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: verified by Ludovic's AI agent (contrib gate 20): unbounded selectors reach the other loaded levels; includes #2559 (End crystals and the dragon) and a main merge with the score-holder and execute origin arms. It passed in this wave's union with main on the Mac mini: the selected parity harnesses (332/332, then 122/122 on the final union), clippy -D warnings and the tests, and lan_e2e with the host on its server thread and in-frame (18/18 each). Thanks @levzzz5154!
🤖 Agent: verified by Ludovic's AI agent (contrib gate 20): the dig stop is covered in the LAN harness (lan_e2e dig_stop passes; includes #2563). It passed in this wave's union with main on the Mac mini: the selected parity harnesses (332/332, then 122/122 on the final union), clippy -D warnings and the tests, and lan_e2e with the host on its server thread and in-frame (18/18 each). Thanks @levzzz5154!
🤖 Agent: verified by Ludovic's AI agent (contrib gate 20): thrown items fly between server and client (lan_e2e thrown passes). It passed in this wave's union with main on the Mac mini: the selected parity harnesses (332/332, then 122/122 on the final union), clippy -D warnings and the tests, and lan_e2e with the host on its server thread and in-frame (18/18 each). Thanks @levzzz5154!
🤖 Agent: verify passed at 80751276f (7 min 38 s, in the range of the last merges: 5-7.5 min). Parity scope selected no harness. Test-only change: the 5 full-content-root mod_content tests are #[ignore]d, and pr_ready runs them when the diff touches what they load. Ready to merge.
🤖 Agent: verified by Ludovic's AI agent (contrib gate 20): an occupied horse gives no inventory, feeding or ride (lan_e2e occupied_horse, riding, mounts pass). It passed in this wave's union with main on the Mac mini: the selected parity harnesses (332/332, then 122/122 on the final union), clippy -D warnings and the tests, and lan_e2e with the host on its server thread and in-frame (18/18 each). Thanks @rdbtCVS!
🤖 Agent: verified by Ludovic's AI agent (contrib gate 20): release notes keep wrapped known issues. It passed in this wave's union with main on the Mac mini: the selected parity harnesses (332/332, then 122/122 on the final union), clippy -D warnings and the tests, and lan_e2e with the host on its server thread and in-frame (18/18 each). Thanks @rdbtCVS!
🤖 Agent: verified by Ludovic's AI agent (contrib gate 20): recipe book settings persist on the server. It passed in this wave's union with main on the Mac mini: the selected parity harnesses (332/332, then 122/122 on the final union), clippy -D warnings and the tests, and lan_e2e with the host on its server thread and in-frame (18/18 each). Thanks @rdbtCVS!
🤖 Agent: verified by Ludovic's AI agent (contrib gate 20): USE_ITEM_COMPLETE finishes the use; eating on the client (lan_e2e eat_full, eating, helduse, consume-release pass). It passed in this wave's union with main on the Mac mini: the selected parity harnesses (332/332, then 122/122 on the final union), clippy -D warnings and the tests, and lan_e2e with the host on its server thread and in-frame (18/18 each). Thanks @Louistuis!
Key bindings and names, toggle keys, mouse options, controller settings,
the clipboard and window options move to their own crate, re-exported under
their old paths. Their unit tests now rebuild in about a second after an
edit instead of rebuilding the client lib's test binary.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: verified by Ludovic's AI agent (contrib gate 20): cushion break particles reach multiplayer players. It passed in this wave's union with main on the Mac mini: the selected parity harnesses (332/332, then 122/122 on the final union), clippy -D warnings and the tests, and lan_e2e with the host on its server thread and in-frame (18/18 each). Thanks @ESHAYAT102!
The five mod_content tests that load the whole content root took minutes of
every `cargo test -p horizon-client --lib` on prepared data. They are now
#[ignore]d; pr_ready runs them when the diff touches what they load, and CI's
verify job runs them filtered with --ignored on its existing build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On playhorizon's runner (CPUs 4-7, 4 harness slots, frames drawn on the CPU)
remote_fireworks still failed in #2215's job after #2589 and #2629: a
screenshot took ~1.5 s (58 ticks for two) beside three other harnesses. The
harnesses in parity_hosts.json's new solo list run alone there, after the
others; bigger machines are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>