Skip to content

Rust + KID pivot — M3 Part 2: mora-cli end-to-end compile#45

Merged
halgari merged 11 commits intomasterfrom
m3-mora-cli-compile
Apr 21, 2026
Merged

Rust + KID pivot — M3 Part 2: mora-cli end-to-end compile#45
halgari merged 11 commits intomasterfrom
m3-mora-cli-compile

Conversation

@halgari
Copy link
Copy Markdown
Owner

@halgari halgari commented Apr 21, 2026

Summary

Delivers the first real mora compile command per
docs/superpowers/plans/2026-04-21-rust-kid-pivot-plan-7-mora-cli.md:

  • mora binary with compile subcommand via clap
  • --data-dir + --plugins-txt required flags; --output optional (defaults to <data-dir>/SKSE/Plugins/mora_patches.bin); --dry-run + --verbose modifiers
  • Opens EspWorld, discovers + parses all *_KID.ini files, runs KidDistributor, writes mora_patches.bin
  • Load-order hash: blake3 digest over canonical load-order representation (plugin names + ESM/ESL flags + master lists, lowercased + NUL-separated), truncated to 64 bits
  • docs/src/mora-cli-reference.md — CLI UX reference

Test plan

  • cargo test --workspace174 tests pass (167 prior + 7 new: 4 end-to-end integration + 1 fixture smoke + 2 load-order-hash)
  • cargo clippy --all-targets -- -D warnings clean
  • cargo fmt --check clean
  • cargo xwin check --target x86_64-pc-windows-msvc --workspace clean
  • ./target/debug/mora compile --help renders correctly

Integration testing

End-to-end integration tests subprocess the compiled mora binary against synthetic Skyrim Data directories:

  • compile_produces_valid_patch_file — builds a plugin with WeapMaterialIron + IronSword, writes a Test_KID.ini with WeapMaterialIron = Weapon, runs mora compile, verifies output PatchFile has correct AddKeyword patch
  • compile_dry_run_does_not_write--dry-run produces no on-disk file
  • compile_bad_data_dir_exits_nonzero — non-directory path exits with code 1 + "data-dir" in stderr
  • compile_empty_kid_ini_set_produces_empty_patches — Data dir with no *_KID.ini produces an empty-but-well-formed patch file

Scope discipline

  • mora compile only. mora check + mora info deferred.
  • Explicit flags. No auto-detection of Skyrim install (Linux Steam paths + Windows registry are polish follow-ups).
  • No auto-install. User owns paths.

Next up

Plan 8: complete KID parity on Weapon + Armor — activate ALL / ANY filter buckets (currently parsed but skipped at evaluation), implement remaining trait predicates (anim type, armor type, DNAM fields on records), parse + honor ExclusiveGroups.

At that point Weapon + Armor rules hit the full KID filter grammar. Other 18 record types then land per-type as Plan 9+ adds the mora-esp record accessors they need.

halgari added 11 commits April 20, 2026 23:45
Delivers the first real `mora compile`: clap subcommand, EspWorld
open, KID INI discovery + parse, KidDistributor run, mora_patches.bin
serialize and write. Adds load_order_hash to mora-esp (blake3 digest
over canonical load-order representation, truncated to u64).

9 tasks across 5 phases. Explicit --data-dir + --plugins-txt flags;
--output defaults to <data-dir>/SKSE/Plugins/mora_patches.bin; --dry-run
modifier. End-to-end integration tests subprocess the built binary
against synthetic Skyrim dirs + KID INIs.
Documents the mora compile subcommand: flags, exit codes, typical
output format, and load_order_hash semantics. Future commands
(check, info) flagged as deferred.
blake3-truncated-to-64-bit digest over a canonical load-order
representation (plugin filenames + ESM/ESL flags + master lists,
all lowercased and NUL-separated). Populates PatchFile::load_order_hash;
runtime verifies on load and refuses on mismatch.
Cli { command: Commands::Compile(CompileArgs) }. CompileArgs exposes
--data-dir, --plugins-txt, --output, --dry-run, --verbose flags.
resolve_output() defaults to <data-dir>/SKSE/Plugins/mora_patches.bin.
Initializes an env-filter-aware subscriber with stderr output, no
timestamps, no targets, no spans — clean log lines for user-facing
output. Respects RUST_LOG; --verbose flips default to debug.
Opens EspWorld, computes load-order hash, discovers + parses KID INIs,
runs KidDistributor, writes mora_patches.bin (or skips on --dry-run).
anyhow::Context wraps every step with user-readable error messages.
Parses args via clap, initializes logging, dispatches to the
requested subcommand. On error, prints the anyhow error chain to
stderr and exits with code 1.
Fixture struct creates a tmpdir with synthetic plugins + plugins.txt,
cleans up on Drop. build_plugin() composes minimal ESM bytes with
optional KYWD/WEAP/ARMO groups. mora_bin() locates the built binary.
4 tests against a built mora binary + synthetic Skyrim dirs:
  compile_produces_valid_patch_file, compile_dry_run_does_not_write,
  compile_bad_data_dir_exits_nonzero, compile_empty_kid_ini_set.
Exercises the full pipeline: argv parse -> EspWorld::open ->
pipeline::compile -> PatchFile serialization -> on-disk bytes.
Whitespace normalization; no functional changes.
blake3's build script compiles C acceleration code when targeting
Windows, which requires llvm-lib (ships in Ubuntu's llvm package).
cargo-xwin installs only the Rust wrapper — the underlying LLVM
toolchain must come separately. Fix for Plan 7 (which first added
blake3 to mora-esp via the load_order_hash module).
@halgari halgari merged commit 538c913 into master Apr 21, 2026
6 checks passed
@halgari halgari deleted the m3-mora-cli-compile branch April 21, 2026 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant