🤖 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): 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): 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>
A manifest line defining or turning on a workspace crate's feature no longer
makes the manifests count, if every source naming the feature (or one it turns
on) changed too, as in a split, where the new crate's files are all new.
#2215 (horizon-items with a test-support feature) now selects 209 harnesses
instead of 354.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cargo.lock is a shared input and every harness depends on its crates'
Cargo.toml, so a crate split (#2160) selected all 352 harnesses although
its moved code reaches 123. With --changed, Cargo.lock and Cargo.toml
changes that only add, remove or move workspace crates (no registry or git
package, version, feature, dependency or build setting changed across them,
compared with the merge base) are left out; the moved code counts through
its own sources. Any other manifest change still counts, as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pr_ready --quick passed #1895 while CI's clippy failed on an unused import in horizon-mods' tests: clippy on the
touched crates and their dependents gives them other features than CI's workspace-wide run (Cargo unifies
features over the packages it builds).
- clippy: CI's two commands as they are. The whole workspace runs with the game's code mods, and the server build
(horizon-client --no-default-features) runs when horizon-client is affected. Warm on the Mac mini, a change to
hud.rs took 14-16 s against 17 s before, and food.rs 22-32 s against 14 s. Each worktree's first run costs
about 3 min once.
- tests stay on the touched crates, with the features CI's workspace run gives them: horizon-client's code mods,
and horizon-mods' runtime, pack and index.
- The Python tests always run, as in CI: some read the crates, the roadmap or the workflows.
- The launcher steps run when CI's launcher job would (tools/ci/rust_changes.py's rule, which also covers the
root manifests and the check itself).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tools/parity_hosts.json's new `known_flaky` lists the harnesses that still flake for a cause not fixed yet,
each with its reason: dedicated_server (its Java client's 1.5 s step timer), remote_fireball (wall-clock
sampling) and world_reopen. One of them that fails runs once more from scratch, and a pass then counts.
Every retry prints a RETRIED line at the end of the run and in the CI job's summary, so a harness that
passes only on its retry stays visible on PR parity and parity-main alike. The existing fresh rerun of a
failure that reused oracle results is reported the same way. A known flaky harness skips that rerun and keeps
reusing oracle results, because flaking doesn't mean its cached oracle runs were wrong. Repeated runs
(--repeat, --flake-check) are never retried.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings #2212 (namespaced furnace RecipesUsed), which save_roundtrip needs:
CI's parity checks out this branch's head, not a merge with main.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: Gate check by Ludovic's AI agent (Claude). The client branch of Squid.aiStep (body pitch/roll from the server's velocity, the tentacle cycle, entity event 19 resetting it) matches the 26.3 bytecode. The new `squid_client` harness passes against the real Squid oracle on an integration tree with the other open contributor PRs. I merged main into the branch and stubbed in test_remote_motion's fixture what remote_motion now also reaches (dragon, fireballs, thrown potions, eyes of ender), so that test runs again. Fixes#1684 is right. Thanks @ESHAYAT102!
OracleReuseTests ran the shim through `#!/usr/bin/env python3` with a PATH
whose Python folder is Homebrew's, which names it only python3.13: the
shim wasn't found (127). The test now gives that PATH a python3 of its own.
test_report_rejects_sources_changed_during_a_run compared a resolved source
path with an unresolved temp root, and macOS's /var is /private/var.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
remote_motion now also hands motion to the dragon, its fireballs, thrown
potions and eyes of ender; the extracted fixture needs those to compile.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: Gate check by Ludovic's AI agent (Claude). Item.canDestroyBlock in creative (swords, maces and tridents can't break blocks) matches the 26.3 bytecode, on the player's prediction and on the server. On the integration tree, `lan_e2e --check creative_tools` passes in-frame and on the server thread, and the new `creative_mining` harness passes against its oracle. I merged main into the branch twice; the second time, lan_e2e.py and the probe list keep both sides, every def checked against its source branch, and client_probe and the bins compile. Fixes#2035 is right. Thanks @ESHAYAT102!
playhorizon.dev now deploys from the private ludovic111/horizon-site, which holds website/'s history. The files
its build still reads from here move out of website/:
- the design tokens to crates/horizon-theme/tokens.css (xtask tokens writes them, tokens_css_is_up_to_date checks them);
- the roadmap's JSON to roadmap/roadmap.json (tools/roadmap.py build);
- the benchmark fixtures to crates/horizon-telemetry-server/tests/fixtures/benchmarks/ (the site keeps a copy);
- the web icons to docs/media/brand/web/ (xtask icons).
pr_ready loses its website area and the tokens special case; rust_changes, the roadmap's links and every doc
that pointed into website/ follow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
verify's cargo runs never build launcher/ (its own workspace), so #2059 and the
registry ratings commit each passed alone and left main's launcher failing to
compile (E0061). The new launcher job runs its rustfmt, clippy -D warnings and lib
tests when a pull request changes the launcher, a crate it builds or the root
manifests, and on every push to main.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: contrib-gate-17 verified this head (26.3 sources, integration tree build, clippy, tests, parity; details in the PR comment). Thanks @levzzz5154!
Twice today (runs 40301239508, 40311712302) mob_ai failed in parity-main, passed when bisect ran it again at
the same HEAD, and the run still ended red, so no game release could follow main for three hours. The
harness step now continues on error and the bisect step gives the verdict: 0 when every failed harness
passes again at HEAD, 1 when they fail at the base too or a merge is named.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two changes so `parity.py --changed` keeps picking the right harnesses once code moves into a crate of its own:
- A harness recorded before the move names the old paths. A changed Rust file of a crate the recorded crates
link (their path dependencies, transitively) but don't name now counts, and the reach search decides.
Before, such a file matched no record and selected nothing.
- A library's root opens once reached code names the crate (`horizon_world::`, `pub use horizon_command as
command`), instead of always. Every crate root was open, so any item of a new crate whose name matched a
name used anywhere counted. On main the selection is the same for 15 of 16 sampled files; for
horizon-world/src/nbt.rs one harness that reached it only through a name match drops out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
capture(true) now calls reset_inventory_clicks; the fixture compiles the
method body against a stub Game.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: gate verified on e3e08911b (main merged). fmt, clippy -D warnings and horizon-client tests pass. lan_e2e with the server-thread host: 131/133, and cursor/falling pass on rerun in both modes. 14 in-frame checks pass. agent_control_e2e: only manage fails, and it fails the same way on main. 82 of the 83 affected harnesses pass. lan_integration flakes under load and is now named-only (nightly). Queued.
The harness runs the whole lan_e2e suite: ~40 minutes on a loaded runner,
and single checks flake under load (barter, riding, shulker_bullets in one
run; cursor, falling in another, all passing on rerun). Selected by
--changed it would run on most gameplay pull requests and on parity-main.
tools/parity_hosts.json gains a named_only table that every automatic
selection (--changed, --failed, the default, --flake-check) leaves out;
naming the harness or --all (the nightly audit) still runs it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: merged main in. The old head's parity failure was server_dimension_players, which passes on main's parity-main. tests/test_parity_reach.py OK.
Check the tool component before server destruction, local mining and remote prediction. Cover vanilla item defaults, overrides and mode-switch cancellation.
Co-Authored-By: OpenAI GPT-6.1 Sol <noreply@openai.com>
The bisect ended on the newest merge when the failed harnesses pass
everywhere now (a flake, or a runner that was missing the sounds), and
on the oldest when they fail everywhere (the runner), and commented on
that pull request either way. It now reruns them at HEAD and at the base
first and names nobody unless HEAD fails and the base passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
macOS temp dirs live under /var, a symlink to /private/var, so the
resolved report path never equalled the unresolved fallback.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The reach parse cache lives in the shared parity folder, keyed by content,
so a new worktree starts warm (written atomically, other worktrees'
entries kept within bounds).
- A harness's reach search stops as soon as it reaches a changed file that
differs in more than its `mod` declarations; partial searches are not
memoized. Declaration diffs are memoized (one git show per file).
- A harness whose changed dependency is outside crates/ is picked without a
search (narrowing always keeps those).
- After PARITY_REACH_BUDGET seconds (default 180) the remaining harnesses
count every source their probes link.
- crate_of is cached; no pathlib in the hot paths.
Same 79 harnesses on the 19-file diff from contrib-gate-16; CPU 19.9 s cold /
16.6 s warm before, 13.1 s cold / 9.9 s warm after (Mac mini under load).
parity.yml: skip the prepare_output check for heads made before #1947 (no
OUTPUT_VERSION, no tool): the job runs main's workflow on the head's files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: verified: OUTPUT_VERSION = 1 and output-versions.txt carry the digest measured on 10 CI preparations. tools/prepare_output.py check passes on v0.2.64's preparation and fails on v0.2.47's. This head's own parity job prepares with its preparer and checks the digest. Merging.
Disk: clear_large_outputs only looked at .local directories named after the
harness, so the 174 harnesses writing to rust-<name>-parity kept every dump
(86 GB in one runner checkout, 13 GB for state_provider alone). It now
clears those too, keeps vanilla outputs only up to 256 MB (larger ones cost
more disk than rerunning their oracle), and handles shard names.
collision, world and geometry dropped one mkdtemp run directory per run
(11 GB): each run now removes the earlier ones.
Time: harnesses inherited the runner's stdin, a pipe on GitHub's runner, and
parity_shim never reuses an oracle run whose stdin is a pipe, so oracle reuse
never worked on CI. Harnesses now get /dev/null.
CI: parity.yml falls back to the head's own selection when the names main's
`--list` printed don't match its summary count.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
parity-main runs the vanilla harnesses on every push to main, one run at a
time: merges that land during a run wait in one pending run, which checks
every merge since main's last green parity-main (tools/parity_main.py base,
then parity.py --changed). A failure is bisected over the batch's
first-parent merges, running only the failing harnesses, and the breaking
merge's pull request gets a comment.
Game releases ship only a commit both checks and parity-main passed on
(release_train.py; release.yml also starts when parity-main finishes; a
forced release doesn't wait). The per-PR parity job now runs only for a PR
that changes a harness, an oracle, a probe or the runner, or carries
run-parity.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ludovic's rule (2026-10-26): runner_pause.py pauses at once on keyboard, mouse or gamepad input
(read from /dev/input, only whether bytes came), on an unlocked session touched in the last
15 min, at 90 °C, on a game or the GPU. Fixes the service start: the link loop's last test
failed the script under set -e.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`--changed` / `--changed-files` now narrow each harness's recorded Rust
sources to those its probes can reach (tools/parity_reach.py): an item-level
reachability walk from the probe modules a harness ran (or the binary it
built) over free items, inherent methods, trait impls and macros, matched by
name so it only over-approximates. Parent modules count through their `mod`
declarations, compared with the merge base. A harness whose probe can't be
placed keeps every source; `--by-crate` turns the narrowing off.
On the last 20 PRs merged on 2026-10-25: 2255 -> 1061 harnesses picked,
2384 -> 1592 harness-minutes. Replaying the week's 61 failed CI parity runs,
every failed harness the old selection picked is still picked; LLVM coverage of
six harnesses' probes executes only kept files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>