felis-client-core no longer builds with default-features = false (breaks the wasm reuse path) #195
Labels
No labels
priority/P0
priority/P1
priority/P2
release/v0.1.0
status/blocked
status/planned
type/bug
type/design
type/test-gap
type/tracker
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
natsukium/felis#195
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
felis-client-coreno longer compiles withdefault-features = falseat105b089979369fd310757375af3df7900ae7e523. Three modules that are declaredunconditionally reach for items the
nativefeature gates, so the portablecore the crate documents as the wasm reuse path fails to build on every
target — wasm32 and the host alike.
crates/felis-client-core/src/lib.rs:9states the contract:docs/reference/workspace.md:104namesfelis-web-componentas the consumerof exactly that build.
Reproduction
(The same failure reproduces on the host target — the first two errors are
target-independent.) Verified from
felis-web-componenton branchfollow-felis-105b0899,nix develop -c cargo build --lib --target wasm32-unknown-unknown:What each error is
env_basecaptures this process's environment for aSpawnArgs.env_baseandtypes it against
connector::Carrier, which isnative-only. A browserclient dials nothing and creates nothing, so the module has no business in
the portable set.
shader_clockis the GPU renderer's frame clock and readsconfig::ShaderAnimation, alsonative-only.pipe'splatform_path/nodename/process_is_liveexist only undercfg(unix)andcfg(windows).wasm32-unknown-unknownis neither, so thisone is wasm-specific on top of the feature split.
Why nothing caught it
dev/flake-module.nix:33putswasm32-unknown-unknownon the toolchain withthe comment "so CI guards felis-client-core's portable core against
feature-split bitrot", but no recipe or workflow builds that configuration —
git grep wasm32outsidedocs/finds only the toolchain line and twocomments. The guard the comment promises does not exist, which is how the
three modules drifted.
Impact
felis-web-componentcannot build against felis main at all. Itsfollow-felis-105b0899branch adapts the whole wasm core to the reset wire(verified green against a locally patched felis: 25 + 9 wasm tests pass, clippy
clean) but every CI gate stays red on this, so the PR cannot be merged until
felis builds.
Suggested fix
Gate the three modules behind
native(what the local patch did to verify thefollow), or split the two
pipehelper sets so the portable half stands alone,then add the guard the flake comment claims:
cargo check -p felis-client-core --no-default-features --target wasm32-unknown-unknownas ajust checklayer and a CI step.Out of scope for the follow
The fix belongs to felis: a downstream cannot exclude a dependency's modules,
and
[patch]ing felis from the component would fork the crate the componentexists to reuse verbatim.
Triage plan (2026-09-07)
Verdict: accepted,
priority/P1. The wasm/portable core is a documented contract (crates/felis-client-core/src/lib.rs, itsCargo.toml,docs/reference/workspace.md,docs/explanation/architecture/overview.md) with a real consumer blocked on it (felis-web-component), and the tag would ship a doc claim that does not compile.Verified on a detached
origin/maincheckout:cargo check -p felis-client-core --no-default-featuresfails with 2 errors on the host (crate::connectorinenv_base.rs,crate::configinshader_clock.rs, bothnative-gated modules) and 7 onwasm32-unknown-unknown(plus thecfg(unix|windows)-only helpers inenv_base.rsandpipe.rs). Bisected:9028ed94introduced the gate and built clean on wasm32;8c8547ca(shader clock, 2026-08-14) is the first break;b118dbe8/9a20b398/47d4c1fe(pipe) anda011c611(env_base) added two more. Three independent regressions in three weeks because no guard exists:dev/flake-module.nixinstalls the wasm32 target and its comment says CI guards the split, but no justfile recipe, workflow step, or flake check ever used it;pr.ymlruns only--all-features.Approach:
crates/felis-client-core/src/lib.rs: gateenv_base,shader_clock, andpipebehind#[cfg(feature = "native")]. All three are host-process concerns; their only consumers (felis-cli,felis-client) build with default features. Nopipesplit — nothing in it is portable.just check-portable=cargo check -p felis-client-core --no-default-features --target wasm32-unknown-unknown(and clippy in that config so-D warningscatches deadcfgleftovers); add it to thecheckaggregate and as one step inpr.yml's build job (mirror inrelease.ymlif it repeats the gate). Prefer the cargo step over a crane check, matching the clippy/nextest precedent.dev/flake-module.nixcomment only if the guard lands somewhere other than "CI". Commit scopesclient-core:+ci:. No CHANGELOG (no CLI/config/wire change). Size ≈ 20 lines.Risk: gating
piperemovespipe::Origin/StagedRegionfrom the portable set — no portable consumer exists; note it in the commit body. Iffelis-gridorfelis-protocolgrew a non-portable dep since8c8547ca~1, the new guard will surface it; that is the guard working.