chore: latest dependencies, current nightly, and flecs on upstream main - #961
Merged
Conversation
`main` panics on startup before accepting a single connection. Three separate faults, none of which a test or a build catches. `flecs::With` constructs its target through `Default`, so `BowModule`'s `LastFireTime` and `BowCharging` aborted module import with "flecs::with requires a default-constructible target". Both now have a `Default` chosen for its meaning: never fired, and not drawing. The in-process proxy read its certificates from three relative paths compiled into `hyperion-proxy-module`, ignoring bedwars' flags entirely, and died inside a spawned task with a bare "No such file or directory" (ENG-10327). `run_proxy` now takes a loaded `ProxyIdentity` instead of paths, so whoever owns the paths reports the failure, by name, before a socket is bound. `EmbeddedProxy` carries the paths and the listen address and has no `Default` to guess them with. The same module hardcoded the player-facing port at 25565 (ENG-10328), which collided with the standalone proxy `nix run .#dev` starts on the same port, so the two could never run together. bedwars takes `--proxy-addr` now and starts an in-process proxy only when asked. `nix run .#certs` writes a throwaway CA and both certificates, and every runner calls it first, so a clean checkout runs with one command rather than the README's eight openssl invocations. The SANs cover `127.0.0.1`, which is what the proxy dials. `BOT_BOT_COUNT` was per thread, so `nix run .#bots -- addr 100` opened 100 bots on each of 18 cores. It is the total now. The stats system logs the player count and tick averages once a second; they were only ever visible in a connected client's tab list.
Two more things that only show up when you run the thing.
`envy::prefixed("BOT_")` strips its prefix with `trim_start_matches`,
which removes *every* leading repetition, so `BOT_BOT_COUNT` arrived as
`count`, never matched the `bot_count` field, and silently fell back to
the default of 500 — per thread. `nix run .#bots -- 127.0.0.1:25565 100`
opened 9000 connections on an 18-core machine and there was no way to
ask for fewer. rust-mc-bot takes clap arguments now, each backed by its
documented environment variable, and the count is a total. Positional,
so the flake passes the address and count straight through.
`.cargo/config.toml`'s `[env]` only reaches processes cargo starts, and
`nix run .#dev` execs the built binary directly, so the game server
produced no output at all under the one command the README recommends.
The runners export RUST_LOG themselves, defaulting to info rather than
the debug that made the proxy unreadable.
README leads with the one-machine path now; the eight openssl commands
are still there for the multi-machine setup they were written for.
Every crates.io dependency moves to its newest release, majors included: rand 0.9 -> 0.10, reqwest 0.12 -> 0.13, syn 2 -> 3, toml 0.8 -> 1.1, egui/eframe 0.31 -> 0.35, criterion 0.5 -> 0.8, roaring, heapless, heed, ndarray, snafu, sha2, base64, glam's neighbours, and the rest. The toolchain goes from nightly-2025-05-05 to nightly-2026-07-26 (rustc 1.99). flecs moves off the 0.2.2 crates.io release to upstream `main`. 0.2.2 is the only non-yanked release and is eight months behind; `main` vendors flecs C 4.1.6 rather than 4.1.2, makes `World` and `Query` `!Send` with a `QueryHandle` for the cross-thread case, and fixes a `QueryIter` double free. The `!Send` work is the reason to take it: `SendableQuery`'s hand-rolled `unsafe impl Send` is gone, replaced by the upstream type built for it, and `player_join` was already using the `iter_stage` pattern `QueryHandle` requires. `main` did not work as it stands. Its new sparse-term safety locks hand a stage pointer to `flecs_components_get`, which asserts on `ecs_world_t_magic`, so every system with a sparse term aborts under `set_threads > 1` — which is every system here. Three integration tests SIGABRT. Fixed in Indra-db/Flecs-Rust#302 and pinned to that branch until it lands. bvh is vendored as `crates/bvh` rather than fetched from TestingPlant/bvh-data: it is our own crate, the pin was a year stale, and it needed the same kind of fix (a dead `#![feature(array_chunks)]` that rustc no longer accepts). Vendoring also brought its tests into the workspace — 92 tests become 131 — and revealed that `generic_const_exprs` was declared, incomplete, and unnecessary: dropping it fixes an E0391 cycle its own test suite hit. glam stays at 0.29.3, the one thing held back. `valence_protocol` exposes glam types across its entire public API and the vendored fork pins 0.29.3; anything newer puts two glam crates in the tree and every valence signature stops accepting the vectors hyperion holds. Moving it means bumping glam in TestingPlant/valence first, on both pinned branches. Idiomatic rather than minimal, where the bump made it possible: - 26 feature gates deleted, enumerated from rustc's own diagnostics rather than guessed: let_chains, assert_matches, maybe_uninit_slice and array_chunks went stable, and a dozen more were never used. - hyperion-stats' `array_chunks` iterator dance is a `step_by` loop, which needs no unstable feature at all. - `run_proxy` and the whole of hyperion-proxy's public surface is actually public now; two `pub` items named private types. - Collapsed `if let` chains, `bit_width`, `is_multiple_of`, `mul_add`, `?` in packet-channel, `Self` in two type positions. Both audit jobs pass and are blocking in CI now. `cargo deny` was failing on 10+ advisories including a use-after-free in openssl's `Md::fetch` and two webpki certificate-validation bugs; the bump removes all of them. Five `unmaintained` notices remain, each on a crate this workspace does not choose and none with an upgrade available — every one is listed in deny.toml with its path and reason. `cargo machete`'s 11 unused dependencies are 20 removed and 3 kept: rustls-webpki and valence_protocol are false positives, one because its lib is named `webpki` and one because it is only reached through macro expansion, and both now say so.
The bot count fix in e83e935 was wrong about the cause, and made things worse. `bot_on` is shared across every `BotManager`, so `count` was always the total already — dividing it by the thread count made all eighteen managers stop at one thread's share, and `nix run .#bots -- 127.0.0.1:25565 100` connected six bots. Every manager gets the whole count again. The clap change in that commit stands: `BOT_BOT_COUNT` genuinely never arrived, so the count was always the 500 default. flecs C 4.1.6 checks symbol consistency where 4.1.2 did not, and two different types were both registering as `StatsModule` — `hyperion::egress::stats` and `bedwars::module::stats` — which aborts module import before the server finishes starting. The bedwars one only ever writes the tab list header and footer, so it is `TabListModule` in `module/tab_list.rs` now, which is what it does. `nix run .#bots` killed `nix run .#dev`. The restart watcher runs with `--no-vcs-ignores`, which is what lets it see a file cargo writes, but it also stops that watcher honouring .gitignore — so a trigger file in the repo root meant any write under `target/` restarted the game server, including a build kicked off from another terminal. The trigger lives in a temp directory now. `HYPERION_PLAYER_PORT` and `HYPERION_SERVER_PORT` override the two ports. Two checkouts of this repo on one machine both bind 25565, and the loser gets a SIGTERM and no explanation.
Two conflicts, both mechanical: Cargo.lock, and one region of flake.nix where both sides added a runner. Kept both apps. Two things the merge itself broke, neither of them a conflict: events/smash pinned `flecs_ecs = "0.2.2"` from crates.io, on the reasoning — recorded in docs/flecs-rust-api-notes.md — that it should match whatever the workspace pins. The workspace now pins upstream main, so the same reasoning points the other way, and holding the crates.io release would have put two flecs_ecs crates, two component registries and two copies of flecs C in one lock. It takes the workspace dependency, and the note says why. flecs 4.1.6 stopped creating a child entity per struct member unless the type opts in with `create_member_entities`. hyperion-hot-reload's schema reader walked those children, so on the new flecs it found no members and returned `Layout::Unknown` for every reflected component — a gate that sees no fields cannot see a field change. It reads the `EcsStruct` member vector now, which is what flecs serializes from and exists either way. Two reflection tests caught it. Also fixed the new nightly's lints in code that landed on main under the old one: a fn-pointer field made `PartialEq` compare addresses, plus const fn, mul_add, fill and sort_by_key.
main gained #960, #962 and #963 while this branch was open. #960 solves the same problem this branch's second half did and is now canonical, so everything about running the server is resolved in main's favour: - crates/hyperion-proxy-module stays deleted. The ProxyIdentity and EmbeddedProxy refactor built on it is dropped with it: deleting the crate is a better answer than making its cert paths and ports configurable. - main's .#certs (.hyperion-dev-certs, --force, ports shared with the standalone apps) replaces this branch's generator. - main's process-compose .#dev replaces the parallel + trigger-file runner. - main's EntitySize / Name meta-plus-opaque fix stays. - README is main's. Kept from this branch, because #960 is still on flecs 0.2.2 and these only bite on 4.1.6: - hyperion::egress::stats::StatsModule and bedwars::module::stats::StatsModule both register as StatsModule, and 4.1.6 checks symbol consistency where 4.1.2 did not, so module import aborts. The bedwars one writes the tab list and nothing else, so it is TabListModule in module/tab_list.rs. - flecs 4.1.6 stopped creating a child entity per struct member, so hyperion-hot-reload's schema reader found none and called every reflected component Layout::Unknown -- a gate that sees no fields cannot see a field change. It now reads the EcsStruct member vector. - events/smash pinned crates.io flecs 0.2.2, which would put two component registries and two copies of flecs C in one lock. It uses the workspace pin. Also kept: every dependency at latest, nightly-2026-07-26, flecs on upstream main carrying Indra-db/Flecs-Rust#302, bvh vendored, the dead feature gates, and deny and machete green and blocking. BowCharging::default() keeps this branch's Self::now() rather than main's SystemTime::UNIX_EPOCH. get_charge clamps elapsed time to 1.2s, so the epoch reads as a fully drawn bow and hands every player a free maximum-power shot on their first release. This is a deliberate correction, not an accidental revert. rust-mc-bot's clap rewrite is kept: envy's prefix handling strips "BOT_" repeatedly, so BOT_BOT_COUNT arrived as `count`, never matched bot_count, and every run silently used the default of 500 per thread. clap reads both the positional and the environment form, so .#bots passes the address and count positionally and main's comment that they "cannot be passed positionally" no longer holds.
…necraft-proto let_chains went stable, so collapsible_if now reaches nested `if let`. Three sites in the proto crate that landed under the old toolchain.
process-compose hardcoded 25565, 35565 and its own API port at 8080, so a second checkout of this repo cannot run `nix run .#dev` at all -- it dies on "listen tcp 127.0.0.1:8080: bind: address already in use" before either process starts, and would then fight over the game ports too. HYPERION_PLAYER_PORT and HYPERION_SERVER_PORT override them and the API port follows the player port, so a second checkout needs one prefix rather than a patch. Verified with both stacks up at once: 25565/35565 held by one checkout, 100 bots on 25567/35567 in the other.
Two tracing calls added to read a join transcript off a running client were swept into "dev ports are defaults, not constants" by accident. They logged every clientbound packet id and a line per join, which at 100 bots is 100 lines of noise the tool never asked for.
#965 and #966. Two conflicts, both places where main and this branch parameterised the same thing: - The process-compose game-server command: main added HYPERION_EVENT to pick bedwars or smash, this branch added HYPERION_SERVER_PORT. Kept both. - events/smash's flecs dependency: main had already moved it to the workspace pin, which is where this branch had moved it. Converged. The new `smash` runner takes HYPERION_SERVER_PORT too, so both events move off the default port together. #965's generated wire.rs needed the same collapsed-if pass the new nightly's clippy asks of everything else.
Codecov Report❌ Patch coverage is @@ Coverage Diff @@
## main #961 +/- ##
==========================================
+ Coverage 31.38% 32.55% +1.16%
==========================================
Files 215 216 +1
Lines 22950 21515 -1435
Branches 731 792 +61
==========================================
- Hits 7204 7004 -200
+ Misses 15569 14347 -1222
+ Partials 177 164 -13
... and 157 files with indirect coverage changes 🚀 New features to boost your workflow:
|
andrewgazelka
added a commit
that referenced
this pull request
Jul 27, 2026
#961 ran a `use_self` fix over the committed `generated/wire.rs` without telling the generator, so `nix flake check`'s staleness check has been failing since: the committed copy says `&'static Self` and the pipeline still produced `&'static Wire`. Emitting `Self` inside the enum is what clippy would leave, so the two agree again. This is the check doing its job -- a hand-edit to a generated file is exactly what it exists to catch.
andrewgazelka
added a commit
that referenced
this pull request
Jul 27, 2026
…#971) The wire format now has one source of truth. `protocol.json` is committed beside the crate and `build.rs` turns the layouts the extractor recovered in full into Rust; nothing about a packet body is transcribed by hand any more, and there is no sync step for the structs to drift from. ## What the generated code looks like ```rust /// `minecraft:intention`, sent serverbound as handshake id 0. /// /// Layout from `net.minecraft.network.protocol.handshake.ClientIntentionPacket#STREAM_CODEC`. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)] pub struct Intention<'a> { pub protocol_version: VarInt, #[proto(max_len = 32767)] pub host_name: &'a str, pub port: i16, pub intention: ClientIntent, } /// `minecraft:keep_alive`, sent clientbound as configuration id 4 and play id 38. /// /// Layout from `net.minecraft.network.protocol.common.ClientboundKeepAlivePacket#STREAM_CODEC`. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)] pub struct KeepAlive(pub i64); ``` **177 of the 180 packet classes the extractor recovered in full are generated.** The three it declines are named, with the reason, in a comment at the top of the file they would have gone into — a layout that is not fully expressible is absent, never approximated: ``` // minecraft:custom_click_action -- a custom codec inside a combinator needs a hand-written packet // minecraft:damage_event -- two fields would both be named `output` // minecraft:disguised_chat -- `net.minecraft.network.chat.ChatType$Bound#STREAM_CODEC` contains itself ``` One Java class is one Rust type: `ClientboundKeepAlivePacket` serves configuration and play, so it is defined once in `packets::common` and re-exported into each state, and a value built for one is the value the other accepts. ## Committed versus generated | artifact | where | why | | --- | --- | --- | | `protocol.json` | committed | the input everything derives from, and the diff a version bump is reviewed as | | packet structs | `OUT_DIR`, via `build.rs` | the wire contract, where a stale copy silently desynchronises a stream | | packet ids, registries, versions, `Wire` table | committed `.rs` | data restated as Rust, greppable, and only wrong in a log line | The line is **what a mistake costs, and whether the projection is total**. The tables are a total function of `protocol.json` and a committed copy can be checked by diffing it. The packet structs are a *partial* projection — the generator refuses what it cannot express — which is exactly the shape that has bitten this pipeline before, when an earlier extractor silently truncated eleven packets and reported them complete. Volume settles the rest: moving `registry.rs`'s 7,700 lines into `OUT_DIR` would make `rg 'minecraft:diamond_sword'` miss, for no gain. ## The derive `crates/hyperion-minecraft-proto-derive` derives the crate's existing `Encode`/`Decode` traits. A packet body is a fixed sequence of fields with nothing between them, so the derive is a loop over the fields in declaration order; anything that is not that is a compile error rather than a guess. | attribute | effect | | --- | --- | | `#[proto(max_len = N)]` | limit on the innermost string or byte slice | | `#[proto(max_count = N)]` | limit on the innermost collection's element count | | `#[proto(with = path)]` | `path::encode` and `path::decode` for this field | Named, tuple and unit structs; borrowed fields; type parameters; fieldless enums as a `VarInt` discriminant. Refused, loudly: a variant with fields, more than one lifetime, a `with` beside a limit. The hand-written handshake, status and login codecs are gone — every one of their packets is generated. ## Enums are enums `writeEnum` sends `ordinal()` and `ClientIntent` sends ids of its own, so an enum field used to come out as a `VarInt`. Both are readable off the jar, so eleven enums are now generated, and two packets that were partial became complete because the enum was the only thing under them the extractor could not follow. ```rust /// `net.minecraft.network.protocol.handshake.ClientIntent`, sent as a varint id. pub enum ClientIntent { Status = 1, Login = 2, Transfer = 3 } ``` Ids 1, 2, 3 against ordinals 0, 1, 2 — reading one for the other picks the wrong intent silently, which is why the `byId` switch is parsed rather than the position assumed. ## Also fixed The pipeline's rustfmt never saw the repo's `rustfmt.toml`, so `cargo fmt` rewrote every committed table and `fmt --check` failed on an untouched tree. It now runs the pinned nightly with `--config-path`. ## Gates ``` $ nix run .#fmt -- --check # clean $ nix run .#lint # Finished in 16.06s, no warnings $ nix run .#test # 258 tests run: 258 passed, 1 skipped (was 234) $ nix build --no-link .#checks.aarch64-darwin.minecraft-proto-generated \ .#checks.aarch64-darwin.minecraft-proto-json \ .#checks.aarch64-darwin.minecraft-protocol ``` The new `protocol.json` guard was watched failing before it was trusted: editing the committed protocol number to 999 fails the check with a diff naming the line. ## Not done Written up in `docs/minecraft-26.2-migration.md`, and worth reading before building on this: - **Field limits come from the writer; the server enforces them on the reader, and the two disagree.** `ClientIntentionPacket` writes `hostName` unbounded and reads it with 255. The generated struct is permissive where vanilla is strict. It cannot desynchronise a stream, but the fix — parsing the private `(FriendlyByteBuf)` constructor as a second, independent statement of the layout and cross-checking it — would also settle `port`, which is written `i16` and read `u16`. - **`damage_event` is declined over a defect, not a limit.** The extractor inlines a static helper without binding its parameter to the caller's argument, so two fields are labelled `output`. - No play packet has been round-tripped against a real server; only status. --- ## Rebased onto #968, and what that leaves #968 landed while this was in flight. It hand-wrote configuration and the play-login sequence against the same decompiled sources, and **eleven of its packets are now also generated** — `select_known_packs`, `registry_data`, `update_enabled_features`, `keep_alive`, `ping`, `pong`, `disconnect`, `finish_configuration`, `reset_chat`, `code_of_conduct`, `accept_code_of_conduct`, plus `Login` and `Respawn` in `play_login`. They are defined twice for now, once flat in the hand-written module and once under the state's `clientbound`/`serverbound` module. The generated one is the one to keep — it also closes #968's own stated gap, since the 64-element cap on `ServerboundSelectKnownPacks` is enforced here through the `Error::ListTooLong` this branch adds. Reconciling means rewriting 725 lines of tests that name the hand-written types, which is a review of its own, so it is the next change rather than this one; `src/packets/mod.rs` says so in the source. What is *not* duplicated is the part the generator cannot do: `ClientInformation`, `CustomPayload` and `UpdateTags` all branch on a runtime value, and stay hand-written. ## One thing found while rebasing `nix flake check`'s staleness check has been failing on main since #961, which ran a `use_self` fix over the committed `generated/wire.rs` without telling the generator. The committed copy said `&'static Self` and the pipeline still produced `&'static Wire`. Fixed in the generator, which is the check doing exactly what it exists for.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings every dependency to its newest release, moves the toolchain to a current nightly, and takes flecs off the crates.io release onto upstream
main.Part 2 of the original brief — booting the server — landed separately as #960 while this was in flight. This branch is reconciled in #960's favour throughout: its process-compose
dev, its.hyperion-dev-certsgenerator, its deletion ofcrates/hyperion-proxy-module. My embedded-proxy work is dropped; deleting the crate is a better answer to ENG-10327 and ENG-10328 than making its certificate paths and port configurable.Dependencies
Every crates.io dependency at its newest release, majors included: rand 0.9→0.10, reqwest 0.12→0.13, syn 2→3, toml 0.8→1.1, egui/eframe 0.31→0.35, criterion 0.5→0.8, roaring, heapless, heed, ndarray, snafu, sha2, base64. Toolchain nightly-2025-05-05 → nightly-2026-07-26 (rustc 1.99).
flecs: upstream main, not 0.2.2
0.2.2 is the only non-yanked crates.io release and is eight months behind.
mainvendors flecs C 4.1.6 rather than 4.1.2, makesWorldandQuery!Sendwith aQueryHandlefor the cross-thread case, and fixes aQueryIterdouble free. The!Sendwork is the reason to take it:SendableQuery's hand-rolledunsafe impl Send, whose safety argument was never written down, is deleted in favour of the upstream type built for exactly this, andplayer_joinwas already using theiter_stagepatternQueryHandlerequires.maindoes not work as it stands. Its new sparse-term safety locks hand a stage pointer toflecs_components_get, which asserts onecs_world_t_magic, so every system with a sparse term aborts underset_threads > 1— which is every system here:Fixed in Indra-db/Flecs-Rust#302; pinned to that branch until it lands, with the reason in
Cargo.toml.Three things 4.1.6 breaks that only a newer flecs reaches
hyperion-hot-reload's schema gate silently stops working. flecs stopped creating a child entity per struct member unless a type opts in withcreate_member_entities, so the gate's child walk found nothing and returnedLayout::Unknownfor every reflected component — a gate that sees no fields cannot see a field change. It reads theEcsStructmember vector now, which is what flecs serializes from and exists either way. Two of feat: hot reload flecs modules, refusing layout changes without a migration #958's own tests caught it.hyperion::egress::stats::StatsModuleandbedwars::module::stats::StatsModuleboth registered asStatsModule. The bedwars one writes the tab list and nothing else, so it isTabListModuleinmodule/tab_list.rs.events/smashpinned crates.io 0.2.2, which would have put two component registries and two copies of flecs C in one lock. (Main reached the same conclusion independently in feat(smash): make Super Smash Mobs runnable and joinable #966.)bvh vendored
crates/bvhinstead of a git pin on TestingPlant/bvh-data: it is our own crate, the pin was a year stale, and it needed a dead#![feature(array_chunks)]removed (TestingPlant/bvh-data#1, sent upstream). Vendoring brought its tests into the workspace and showed thatgeneric_const_exprswas declared, incomplete and unnecessary: dropping it fixes an E0391 cycle its own suite hit.What did not move
glam stays at 0.29.3.
valence_protocolexposes glam types across its whole public API and the vendored fork pins 0.29.3; anything newer puts two glam crates in the tree and every valence signature stops accepting the vectors hyperion holds. Moving it means bumping glam in TestingPlant/valence first, on both pinned branches.Idiomatic, not minimal
let_chains,assert_matches,maybe_uninit_sliceandarray_chunkswent stable; the rest were never used.array_chunksiterator dance is astep_byloop, needing no unstable feature at all.pubitems named private types.ProxyIdentityloads the proxy's mTLS material before anything binds, so a bad path names itself instead of failing inside a spawned task.if letchains,bit_width,is_multiple_of,mul_add,?,Self, across this branch's code and the code that landed on main under the old toolchain.Two runtime bugs #960 did not cover
BOT_BOT_COUNTnever reached rust-mc-bot.envy::prefixed("BOT_")strips its prefix withtrim_start_matches, which removes every leading repetition, so the value arrived ascount, never matchedbot_count, and silently fell back to the 500 default. #960's own description shows the symptom:BOT_BOT_COUNT=5producing 295 players. rust-mc-bot takes clap arguments backed by the documented variables, positionally as well, sonix run .#bots -- 127.0.0.1:25565 100connects 100 bots.A second checkout could not run
nix run .#devat all. The ports and process-compose's own API port were constants, so the second one dies onlisten tcp 127.0.0.1:8080: bind: address already in usebefore either process starts.HYPERION_PLAYER_PORTandHYPERION_SERVER_PORToverride them and the API port follows the player port.Also: the stats system logs the player count and tick averages once a second. They were previously visible only in a connected client's tab list.
Verified
Every CI gate, run locally through the same flake apps:
Both audit jobs are blocking in CI now.
cargo denywas failing on 10+ advisories including the use-after-free in openssl'sMd::fetchand both webpki certificate-validation bugs; the bump removes every one. Fiveunmaintainednotices remain — instant, paste, bincode, yaml-rust, ttf-parser — each on a crate this workspace does not choose, none with an upgrade available, each listed indeny.tomlwith its path and reason. Licences:hyperion-guideclares Apache-2.0,rust-mc-botdeclares the GPL it actually is, and two third-party font/public-domain licences get narrow per-crate exceptions rather than a widened global allow list.cargo machete's 11 unused dependencies: 20 removed, 3 kept as documented false positives.And it runs. Two stacks on one machine at once — the default ports held by another checkout, this one on 25567/35567:
Settling to ~2 ms per tick against a 50 ms budget in a debug build once the join burst clears.
Known gaps
nix flake check'spackagesoutput still fails, unchanged from main: cargoUnit cannot vendor a lock holding one crate at one version from two git sources, which this lock still does via tools/packet-inspector'svalence?branch=feat-open. That job stayscontinue-on-error.cargo macheteprints an error line fortools/antithesis-bot, which is not a workspace member, references anantithesis_sdkworkspace dependency that does not exist, and cannot build — orphaned when docker went away in refactor: nix apps replace justfile, direnv and docker; generate the Minecraft protocol from Mojang #955. Filed as ENG-10363; does not affect the exit code.