Repository navigation
validate/list (CLI hot path) force a cold build of the entire serve+MCP+LSP stack — no minimal-build feature #456
Description
Finding (dogfooding friction)
rivet validate is the hook-critical and CI-critical hot path: the project's own pre-commit hook runs it on every commit, and CI runs it as a required gate. Yet the CLI has no way to build a minimal validate/list/commit-msg-check binary — every build unconditionally compiles the full web-server + MCP-server + LSP stack.
Evidence (rivet-cli/Cargo.toml)
[features]
default = []
wasm = ["rivet-core/wasm"] # the only non-trivial feature
[dependencies]
# ...
axum = { workspace = true } # serve
tokio = { workspace = true } # async runtime
tower-http = { workspace = true } # serve
lsp-server = "0.7" # LSP
lsp-types = "0.97" # LSP
notify = "7" # serve --watch / lsp
rmcp = { version = "1.3.0", features = ["server", "transport-io", "macros", "transport-streamable-http-server"] } # MCPThere is no serve/mcp/lsp feature — default = [] and wasm are the only features. So axum, tower-http, rmcp (full streamable-HTTP MCP server), lsp-server/lsp-types, and notify are compiled into every build, including one whose only job is to validate a one-line artifacts/*.yaml edit for the commit hook.
rivet-core already does this correctly — wasm, reqwest, and the spar-* analysis deps are all optional = true. The coupling is specific to rivet-cli.
Impact / friction
- Every from-source build carries the whole web/MCP/LSP tree:
cargo install rivet, CI's compile step, and a localcargo buildto test a one-line validate change all compile axum/tokio/rmcp/lsp even thoughvalidate/listnever use them. On a disk-constrained machine, a cold rebuild of that tree is multi-GiB. - Correction (verified): the project's pre-commit hook does NOT rebuild — it invokes the already-installed
riveton PATH viaRIVET_BIN:-rivet. So the friction is on from-source builds, not the hook itself. (Original report overstated this; corrected for accuracy.) - Downstream packagers who want only the traceability core must still pull axum/tokio/rmcp.
Suggested fix (additive — preserves published behavior)
Introduce cargo features and keep them in default, so cargo install rivet / the released binary are byte-for-byte unchanged:
[features]
default = ["serve", "mcp", "lsp"]
serve = ["dep:axum", "dep:tower-http", "dep:notify"]
mcp = ["dep:rmcp", "dep:tokio"]
lsp = ["dep:lsp-server", "dep:lsp-types"]
wasm = ["rivet-core/wasm"]…with #[cfg(feature = "serve")] / "mcp" / "lsp" gating the corresponding command handlers and module declarations in main.rs. Then:
cargo build -p rivet-cli --no-default-features # fast: parser + validate + list + commit checks
becomes available for hooks, CI's validate gate, and the dogfooding loop, while the default published binary is unchanged. No distribution-semantics change; purely an opt-in minimal build.
Caveat / scope
The code-side gating (#[cfg] across the serve/mcp/lsp command dispatch in main.rs) is the bulk of the work and needs care so --no-default-features still compiles cleanly. Filing as a friction report + design proposal; the default-feature set is a maintainer call. Reported from the hourly dogfooding loop (verified against rivet-cli/Cargo.toml at dedc8c1).
Activity
docs(artifacts): file REQ-186 — CLI minimal-build feature (validate w…
avrabe commentedon Jun 4, 2026
Triage pass — premise confirmed against
rivet-cli/Cargo.tomlon currentmain:default = []andwasmare the only features;axum,tower-http,rmcp,lsp-server/lsp-types, andnotifyare unconditional dependencies, with noserve/mcp/lspfeatures carving them out. The "Suggested fix" sketch (introduce features, keep them indefault, gate handlers with#[cfg]) is well-shaped, but it's a sketch and several decisions are still open (default-feature set, exactly which modules get gated, howserve --watchinteracts withnotifyifnotifybecomes lsp-only, what the published binary's identity becomes). The "one PR per issue, keep PRs focused" rule means I need those decisions encoded before picking this up.Could you add an explicit
## Acceptance Criteriablock to the issue body? Sketch — feel free to revise / re-scope:Borderline calls worth your input even before AC is final:
notifygo? It's used by bothserve --watchand the LSP file-watch path. Two options: (a) put it underserveand havelspdepend transitively (cleanest), or (b) extract a smallwatchfeature bothserveandlspenable. (a) is the simpler default unless LSP-without-serve is a real use case.tokio— gate or leave? You correctly noted in the body that the only feature iswasm.tokiois currently used for the async I/O paths the serve/MCP/LSP commands need, but validate/list don't need it. If gatingtokiounder any-of(serve,mcp,lsp) is feasible without breaking validate/list, that's the bigger size win; if validate uses any async (e.g. for parallel walk), leave it unconditional and document.rivet-corefeatures? The body notes rivet-core already gateswasm,reqwest, and thespar-*deps. Are any of those also worth--no-default-features-ing on the rivet-cli side, or is the friction strictly CLI-local?Process side-rail (carried from prior triage threads on this repo):
https://pulseengine.eu/blog/is still HTTP 503 — same expired-TLS symptom flagged on #420. The binding workflow guidance can't be consulted, so no PR will land from this triage run regardless. Comment is the AC ask only.Not implemented this run.
Generated by Claude Code — issue-triage agent run 2026-06-04.
Generated by Claude Code
avrabe commentedon Jun 5, 2026
Triaged from the hourly dogfooding loop — valid, verified against
rivet-cli/Cargo.toml.[features]isdefault = [];axum/tower-http/notify(serve),lsp-server/lsp-types(LSP), andrmcp(full streamable-HTTP MCP server) are all unconditional dependencies, so every from-source build compiles the entire web/MCP/LSP tree even for the validate/list/commit-msg-check hot path. rivet-core already gates its heavy deps (wasm/reqwest/spar-*areoptional = true) — the coupling is rivet-cli-specific, as you noted. Your self-correction (the hook invokes the installedriveton PATH and does not rebuild) is also accurate.Filed as REQ-202 (draft) in
artifacts/requirements.yaml(PR #475), capturing your additive design: introduceserve/mcp/lspcargo features and keep them indefaultso the published binary is byte-for-byte unchanged, enablingcargo build -p rivet-cli --no-default-featuresfor hooks/CI/dogfooding. Filed draft rather than implemented because (a) the#[cfg]gating across the serve/mcp/lsp command dispatch inmain.rsis the bulk of the work and needs care so--no-default-featuresstill compiles cleanly, and (b) the default-feature set is — as you say — a maintainer call. Shell-testable acceptance criteria are in the REQ (features declared + in default;--no-default-featuresbuilds and runs validate/list/commit-msg-check;cargo treeshows axum/rmcp/lsp-server absent; default build unchanged).docs(agents): add "Before You Push (Rust)" fmt/clippy guidance + file…
feat(validate): `--new-since <ref>` shows only diagnostics new vs a g…
feat(cli): minimal --no-default-features build excludes serve+MCP+LSP…
release(v0.17.0): bump version + CHANGELOG [0.17.0] (#545)