# Rust minimum-version audit (#53) Status: audit/probe complete; the bounded [MSRV repair plan](msrv-repair-plan.md) is accepted after independent review/closure. Implementation integration is accepted under that current-stable scope after complete stable target partitions, optimized build/replay checks and final independent review. The operator subsequently deprioritized earlier-toolchain compatibility while asking to preserve completed work: remaining local acceptance follows normal stable-toolchain gates. Existing1.75 metadata/check/non-CLI evidence is retained, without claiming unexecuted full CLI/release certification. See the plan's current-scope override. Baseline: `e4cfd4c` (accepted tactical orientation). ## Constraint and observed mismatch The workspace and README advertise Rust 1.75. Existing development and the latest accepted all-target gates used Rust 1.98.1. Actual Cargo 1.75 checks stop before compilation because `Cargo.lock` is version 4. This is not evidence that changing only the lockfile would make the game build. Parent ran `cargo metadata --locked --offline --format-version 1 --filter-platform x86_64-unknown-linux-gnu`, traversed resolved dependencies from all workspace members, and inspected declared package minimums. The reachable graph includes the following packages declaring a minimum above 1.75: | Packages | Resolved version | Declared Rust minimum | |---|---|---| | bincode, bincode_derive | 2.0.1 | 1.85 | | clap, clap_builder | 4.6.6 | 1.85 | | clap_lex | 1.1.0 | 1.85 | | derive_more, derive_more-impl | 2.1.1 | 1.81 | | half | 2.7.1 | 1.81 | | hashbrown | 0.17.1 | 1.85 | | indexmap | 2.14.1 | 1.85 | | jobserver | 0.1.35 | 1.85 | | rayon | 1.12.0 | 1.80 | | rayon-core | 1.13.0 | 1.80 | | serde_spanned | 1.1.1 | 1.85 | | toml | 1.1.5+spec-1.1.0 | 1.85 | | toml_datetime | 1.1.1+spec-1.1.0 | 1.85 | | toml_parser | 1.1.3+spec-1.1.0 | 1.85 | | toml_writer | 1.1.2+spec-1.1.0 | 1.85 | | unicode-segmentation | 1.13.3 | 1.85 | This includes dev dependencies used by the all-target gate; it is not a claim that every package enters the shipped runtime or every target triple. Metadata is not actual minimum-compiler certification. Parent metadata output: session shell `call_Mr6Hgcl3TjAKAzGZwr0DXK4y.stdout`. Only `hexwork-core` and `hexwork-render` inherit `workspace.package.rust-version`. Audio, CLI, content, save, term, UI and worldgen report no package minimum. The dependency investigator found current-stable CI/toolchain configuration, not a minimum-version compiler gate. ## Source compatibility candidates Parent targeted source inspection found four actual post-1.75 API uses: - `crates/hexwork-cli/tests/routes.rs:212`: `std::iter::repeat_n` in the ordinary death-route helper. - `crates/hexwork-ui/src/transfer.rs:376`: `repeat_n` in a bounded presentation test fixture. - `crates/hexwork-save/src/artifact/mod.rs:461`: `Result::inspect_err`. Any replacement must preserve closing the terminal barrier after directory-creation failure and return the original error after durable allocation. - `crates/hexwork-worldgen/src/runtime.rs:504`: `Option::is_none_or`. Any replacement must reject both absent and occupied connector endpoints. This targeted scan is not exhaustive compiler proof. Existing relevant tests include allocation durability/fault tests, `malformed_blocked_connector_column_is_rejected`, connector landing tests, bounded transfer formatting and actual death-route/replay gates. ## Dependency investigation and compatibility boundary The read-only dependency investigator used member manifests, the lockfile, exact locally cached registry manifests and official crate metadata. Its context lacked shell execution; parent supplied the actual locked metadata verification above rather than claiming the investigator compiled anything. The compatible-version candidates it identified include TOML 0.8.23, derive_more 2.0.1, jobserver 0.1.34, clap 4.5.61, half 2.4.1, rayon 1.10.0 with a compatible rayon-core, and older compatible indexmap/unicode-segmentation resolutions. These are investigation candidates, not a frozen graph or verified build. Transitive dependencies and TOML parsing/content behavior still require exact resolution and tests. Bincode is not an unused dependency: `hexwork-save/src/protocol.rs` uses its Encode/Decode traits and contextual bounded decoding throughout the current wire protocol. `demo.rs` and other save paths also use bincode. Stable bincode 2 releases declare Rust 1.85. A bincode 1 downgrade is not a routine version pin and is not authorized. Whether a narrowly maintained bincode 2 source backport can preserve the exact existing bytes and decode-budget semantics is under adversarial review; declared MSRV metadata alone does not prove such a backport impossible. No immutable fixture regeneration, wire/schema migration, canonical-hash change, dependency-wide update or minimum-version increase is authorized by this audit. ## Operator decision status Parent recommended considering an explicit Rust 1.85 minimum to preserve the current dependency graph and save formats, versus retaining 1.75 through a larger compatibility effort. The structured question returned **operator unavailable**, not a selection. This is not approval to change the existing 1.75 constraint. The read-only adversarial second opinion rejected the claim that 1.75 necessarily requires a serialization migration: exact bincode 2.0.1 sources are edition 2021, and its incomplete direct-rustc probe reported unresolved dependency wiring rather than a concrete newer API. That is a feasibility hypothesis, not a build pass. Its unty/virtue output attempts failed on `/dev` permissions and were not accepted as passes. Parent therefore retains the existing 1.75 constraint and authorized only an isolated experiment under `target/msrv-probe-53/`: compile/link exact unchanged bincode 2.0.1, its derive crate and actual feature dependencies using installed 1.75; exercise representative contextual decoding APIs; compare probe bytes with stable. `--ignore-rust-version` is permitted only to test whether the declarations are the sole blocker, never as project acceptance. Registry and game sources, root lockfile and immutable fixtures stay untouched. No permanent backport/vendor dependency is authorized; any such change requires a separate exact plan, provenance/licensing/maintenance review and genuine full fixture/compiler gates. Other RPG work remains separable. ## Accepted probe evidence (not project acceptance) The isolated probe compiled and linked exact unchanged cached bincode 2.0.1, bincode_derive 2.0.1, unty 0.0.4 and virtue 0.0.18 under installed Rust 1.75.0 with `--ignore-rust-version`. Its actual features are bincode default/std/alloc/derive, matching the save dependency; serde is not enabled. Offline registry resolution initially failed, so the disposable manifest uses exact cached path overrides, including resolution-only optional serde metadata. Those absolute cache paths are not an acceptable permanent dependency strategy. Five synthetic API tests passed on both 1.75 and stable: contextual derive/borrow round trip, trailing rejection, per-field and aggregate limits before payload reads, and codec claim limits. Both probe executions produced the same 23-byte hex `50524f4245303533fb2c010568656c6c6f05776f726c64`. The negative control without `--ignore-rust-version` failed on bincode's declared 1.85 requirement. No codec implementation edits were needed. Parent reviewed the source/logs and reran both five-test suites successfully, compared the captured output bytes and verified unchanged root lockfile, root/save manifests and `protocol.rs` hashes. The worker additionally checked 122 cached codec-tree files before/after: none changed. Stable emitted existing upstream lifetime-syntax warnings; no warnings or errors appeared on 1.75. No permanent dependency was added. Evidence lives under ignored `target/msrv-probe-53/` (manifest, main.rs, feature tree, toolchain logs, negative control, encoded bytes and integrity report). These tiny `PROBE053` records are not genuine v4 fixtures. The result supports planning a metadata-only local codec backport; it does not establish full-game minimum-version support, full persistence coverage, optional-feature/platform support or license/maintenance acceptance. Before any repair: freeze exact ownership, dependency/source changes, preservation requirements and tests. Successful minimum-version closure requires an actual locked minimum-compiler build/test gate, consistent member/documentation/CI declarations, current-toolchain quality gates and unchanged genuine save/replay fixture contracts. Platform claims must remain limited to tested targets. Other gameplay integration remains independently actionable; this audit alone does not justify blocking the entire 1.0 goal.