diff --git a/Cargo.toml b/Cargo.toml index 5acb93e..51b8b56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,9 +61,17 @@ similar_names = "allow" multiple_crate_versions = "allow" [features] -# Pick exactly one Lua flavor at build time. v0.1 default is LuaJIT +# Pick exactly ONE Lua flavor at build time. v0.1 default is LuaJIT # (spec §3 Checkpoint 6); lua54 is a buildable fallback for environments # without LuaJIT support (e.g. some CI hosts, big-endian machines). +# +# `luajit` and `lua54` are MUTUALLY EXCLUSIVE — they select mlua's +# mutually-exclusive Lua backends. `--all-features` enables both and CANNOT +# build; the `mlua-sys` build script errors ("You can enable only one of +# the features: …") before this crate compiles, so pmacs can't preempt it +# with a friendlier message — the fix is to build one flavor. See the +# feature matrix in README.md; build a non-default flavor with +# `--no-default-features --features lua54` (audit F-002). default = ["luajit"] luajit = ["mlua/luajit", "mlua/vendored"] lua54 = ["mlua/lua54", "mlua/vendored"] diff --git a/README.md b/README.md index bea0800..51cc6b1 100644 --- a/README.md +++ b/README.md @@ -31,17 +31,49 @@ and send pull requests. ## Build Builds on the toolchain pinned in `rust-toolchain.toml` (Rust -`1.95.0`, edition 2024); rustup selects it automatically. Lua flavor selectable -between `luajit` (default) and `lua54`; both pass the full test suite. +`1.95.0`, edition 2024); rustup selects it automatically. ```sh -cargo build --release # produce target/release/pmacs +cargo build --release # produce target/release/pmacs (LuaJIT) cargo run --release -- # build and run on a file cargo test --workspace # unit + integration tests (all crates) cargo fmt --check cargo clippy --workspace --all-targets -- -D warnings # incl. pmacs-gpu ``` +### Feature matrix + +Cargo features fall into two independent axes. **Do not use +`--all-features`** — it enables both Lua flavors at once, which cannot +build (see below). + +| Feature | Axis | Notes | +| -------- | ---------- | ---------------------------------------------------------- | +| `luajit` | Lua flavor | **Default.** LuaJIT backend via `mlua` (vendored). | +| `lua54` | Lua flavor | Lua 5.4 fallback for hosts without LuaJIT (big-endian, …). | +| `crdt` | Buffer | Opt-in CRDT-backed buffer mode (adds the `loro` dep). v1.0 builds enable it; orthogonal to the flavor. | + +**Exactly one Lua flavor must be enabled** — `luajit` *or* `lua54`, never +both (and never neither). They map to `mlua`'s mutually-exclusive Lua +backends, so `--all-features` (or `--features luajit,lua54`, or +`--no-default-features` with no flavor) fails in the `mlua-sys` build +script with *"You can enable only one of the features: …"*. That check +lives in a dependency cargo builds first, so pmacs can't replace it with a +friendlier error — the fix is to build a specific flavor. Supported build +lines: + +```sh +cargo build --release # luajit (default) +cargo build --release --no-default-features --features lua54 +cargo build --release --features crdt # luajit + crdt +cargo build --release --no-default-features --features lua54,crdt +``` + +CI, `cargo hack`, and distro tooling should iterate the flavors +explicitly (`--no-default-features --features [,crdt]`) rather +than reaching for `--all-features`. Both flavors pass the full test suite; +CI runs the matrix on every push. + Release-only perf gates (M5 keystroke-to-render, M6 ingest/RSS/cancel and scrollback navigation/search) are `#[ignore]`'d during normal test runs and exercised in CI under dedicated jobs. diff --git a/docs/repository-audit-2026-07-03.md b/docs/repository-audit-2026-07-03.md index e860b52..0fb2979 100644 --- a/docs/repository-audit-2026-07-03.md +++ b/docs/repository-audit-2026-07-03.md @@ -112,6 +112,22 @@ lua54`, and `--features crdt`. If possible, add a clearer crate-local compile error for simultaneously enabled Lua flavors so users see a pmacs-specific message before the `mlua-sys` failure. +Resolution (PR TBD): documented the feature matrix explicitly — a table in +`README.md` §Build (the two Lua flavors + orthogonal `crdt`, the supported +build lines, and an explicit "don't use `--all-features`"), a `# Lua flavor +features` section in `src/lib.rs`'s crate docs, and an expanded `Cargo.toml` +`[features]` comment. CI already avoids `--all-features` (it iterates the +flavors explicitly), so no CI change was needed. + +The suggested crate-local `compile_error!` was **investigated and rejected as +unreachable**: the flavor check lives in the `mlua-sys` *build script*, which +cargo compiles before the `pmacs` crate, so any mis-set flavor (both, or +neither) fails there first and `pmacs`'s own `compile_error!` never evaluates +— confirmed empirically for both cases. A dependent crate cannot preempt a +dependency's build failure, so the honest mitigation is the documented matrix +rather than a guard that can never fire. The docs state that the actual error +surface is the `mlua-sys` message. + ### F-003 - Medium - `pmacs-gpu` can appear hung when attached to a non-CRDT daemon Evidence: diff --git a/src/lib.rs b/src/lib.rs index 4581bb1..8e35f45 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,21 @@ //! * [`worker`] --- work-stealing pool with cooperative cancellation (M3.1) //! * [`message_bus`] --- typed in-process bus with `MessagePack` codec (M3.2) //! * [`async_runtime`] --- main-thread dispatcher + tick over the bus (M3.3) +//! +//! # Lua flavor features (audit F-002) +//! +//! Exactly **one** Lua flavor must be enabled: `luajit` (the default) **or** +//! `lua54`. They select `mlua`'s mutually-exclusive Lua backends, so +//! enabling both — most commonly via `--all-features` — or neither is a +//! hard build error. The `crdt` feature is orthogonal and composes with +//! either flavor. See the feature matrix in `README.md` / `Cargo.toml`. +//! +//! Note: a misconfigured flavor set surfaces as an **`mlua-sys` build-script +//! error** ("You can enable only one of the features: …"), not a +//! pmacs-labeled one. That check lives in a *dependency*, which cargo +//! compiles before this crate, so pmacs cannot intercept it with its own +//! `compile_error!` — the mitigation is the documented matrix (don't reach +//! for `--all-features`; build an explicit flavor). pub mod ansi; pub mod async_runtime;