Skip to content

validate/list (CLI hot path) force a cold build of the entire serve+MCP+LSP stack — no minimal-build feature #456

@avrabe

Description

@avrabe

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"] }  # MCP

There is no serve/mcp/lsp featuredefault = [] 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 local cargo build to test a one-line validate change all compile axum/tokio/rmcp/lsp even though validate/list never 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 rivet on PATH via RIVET_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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions