levzzz 2dfb8c10b7 feat: implement deterministic Horizon Mixins MVP
Add declarative planning, private same-crate helpers, AST transforms, atomic staging, locked Cargo checks, compilation fixtures, snapshots and Linux CI. Verify an isolated pinned horizon-core prototype and record build measurements.
2026-10-28 00:25:26 +05:00
2026-10-27 23:58:07 +05:00
2026-10-27 23:52:34 +05:00

horizon-mixins

A working stable-Rust CLI for deterministic, build-time source mixins for Horizon. The MVP implements declarative TOML mods, HEAD, BEFORE_CALL, OVERWRITE, JSON planning, atomic Linux staging, and compilation-tested fixtures. Native mods run with your user privileges.

Pristine Cargo workspace + independent mod bundles
    → index source → validate combined plan → transform AST
    → separate staged workspace → cargo test --locked --offline

The three workspace crates are horizon-mixins-core (manifests, indexing, planning, diagnostics), horizon-mixins-transform (AST rewriting), and horizon-mixins-cli (the horizon-mixins binary). Rust 1.95.0 and Cargo.lock are pinned. Cargo metadata and builds use offline, locked dependency resolution. Run cargo fetch --locked once to populate the tool's dependencies.

Build and run the complete two-mod fixture:

cargo build --locked -p horizon-mixins-cli
./target/debug/horizon-mixins plan \
  --workspace fixtures/game --mods fixtures/mods --out target/plan.json
./target/debug/horizon-mixins apply \
  --workspace fixtures/game --mods fixtures/mods --out target/modded-game
./target/debug/horizon-mixins check \
  --workspace fixtures/game --mods fixtures/mods --out target/modded-game \
  --trust-native-mods

plan writes the full validated plan to --out. apply and check rebuild that plan from pristine source, then stage all input files. They never patch the original checkout. check executes the staged workspace's tests; it requires explicit native-code trust. Successful commands print JSON to stdout; failures print a structured diagnostic to stderr and exit nonzero. JSON plans are review artifacts; the CLI does not execute saved plans.

check --package NAME limits Cargo to a package; --target-dir PATH selects a reusable, locked target directory. The default target directory is a stable sibling of the stage. Outputs, mods and originals must be separate. Existing output directories need the generated stage marker. Unchanged files keep their bytes and mtimes, including across publication of changed stages.

A bundle contains horizon-mixin.toml and helper .rs files. For example:

[mod]
id = "movement"
version = "0.1.0"
priority = 100

[[injection]]
id = "head"
target = "fixture_game::entity::advance"
kind = "HEAD"
helper = "head.rs"
bindings = [{ name = "entity", ty = "&mut Entity", value = "&mut *entity" }]
// head.rs: compiled as a local function inside the target function.
fn head(entity: &mut Entity) {
    entity.velocity += 3; // Private fields in the target module are accessible.
}

Helpers use explicit typed parameter bindings. They are compiled in the game crate and introduce no game→mod→game Cargo cycle. All selectors resolve on the original AST; same-site hooks run by priority descending, mod ID ascending, then injection ID ascending. An OVERWRITE conflicts with every other hook on its function.

BEFORE_CALL requires an exact syntax selector, explicit total require, and zero-based ordinal. It supports a complete expression statement, plain let initializer, or block/function tail. Calls nested in larger expressions are rejected because wrapping them can change temporary drop timing. Macro sites, unresolved cfg, async/closures/?, generic/unsafe/const targets, and ambiguous source identities are rejected. Rust checks privacy, types and borrowing in check; successful planning alone does not guarantee compilation.

Validate the implementation:

python3 tools/feasibility.py
cargo fmt --all --check
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test --workspace --locked
python3 tools/benchmark.py # fresh target/benchmark; use --out for another run

The integration suite includes generated source/plan snapshots, positive and negative compilation, deterministic ordering, immutable originals, stale-source rejection, concurrent checks, and unchanged mtimes. Linux CI runs the same checks.

An isolated test against the complete horizon-core crate from commit 028f60881678a9a0e3e198f693a82858fa475c76 passed, including two independent HEAD hooks in jmath::atan. Reproduce it using your local clone:

python3 tools/horizon_prototype.py --horizon /home/levzzz/Documents/horizon

It exports committed crate sources into a fresh target/horizon-prototype, uses an isolated workspace manifest/lockfile, runs upstream tests and generated probes, and records timings. It does not build the full game or launcher. No upstream checkout is edited; no Minecraft assets or prepared resources are used.

Further documentation: API, transformations, architecture, staging and cache, security, roadmap, feasibility and measurements. Advanced injection kinds, launcher integration, semantic resolution, and a complete executable cache remain future work. License: MIT.

S
Description
Compile-time source mixins for Horizon (by levzzz5154)
Readme MIT
474 KiB
0 Stars 1 Watchers 0 Forks
Languages
Rust 98.4%
Python 1.6%