Skip to main content

Module stability

Module stability 

Source
Expand description

§Stability, versioning & the path to 1.0

How far each crate has settled, what a version number promises, the MSRV contract, and the gate this workspace holds itself to before tagging a 1.0.

§Versioning

Every crate is versioned and published independently and adheres to SemVer; each has its own CHANGELOG.md (Keep a Changelog) and is tagged <crate>-v<version>. There is no workspace-wide version.

While a crate is pre-1.0 (0.x), a SemVer minor bump (0.x → 0.(x+1)) may carry breaking changes and a patch (0.x.y → 0.x.(y+1)) is non-breaking — the standard Cargo ^0.x interpretation. Breaking changes are allowed at 0.x and called out in the changelog’s ### Changed/### Removed. After a crate reaches 1.0, it switches to strict SemVer: breaking changes require a major bump.

Because the crates depend on each other (vcs-corevcs-git/vcs-jj; the wrappers → the foundational vcs-diff/vcs-cli-support), each intra-workspace dependency carries a ^MAJOR.MINOR requirement that must stay in range when a dependency crosses a boundary — see the release process in AGENTS.md and the publish ordering in release.yml.

§Stability tiers

All crates are pre-1.0 today — the API may still change. Relative maturity:

CrateVersionTierNotes
vcs-diff0.1settlingSmall, pure (diff model + parser, Version); shape unlikely to change.
vcs-cli-support0.1settlingThe argv guard, fetch policy, and error classifiers — a narrow, stable surface.
vcs-testkit0.1stable-ish (dev-only)Test fixtures; only a dev-dependency, so churn never reaches a release build.
vcs-git0.4maturingBroad surface, consumer-validated; new typed methods still land (additive).
vcs-jj0.4maturingTracks jj, whose CLI/template surface churns — see the CI version matrix.
vcs-github0.4maturingThe gh PR/issue/run/release surface; additive growth.
vcs-gitlab0.1newThe glab lean MR lifecycle; argv/JSON pinned by hermetic fixtures, only version/auth smoke-tested against the real binary — expect movement.
vcs-gitea0.1newThe tea lean PR lifecycle (narrower — see its capability notes); expect movement.
vcs-forge0.1newThe forge facade + unified DTOs; the unification will grow as the wrappers do.
vcs-core0.2evolvingThe facade’s common surface grows as cross-backend needs surface (e.g. snapshot).
vcs-watch0.1newRepo-event stream over vcs-core; the workspace’s first runtime-tokio + streaming API — the event set and the API may still shift.
vcs-mcp0.1newMCP server (a lib + the vcs-mcp binary) over vcs-core/vcs-forge; the workspace’s first binary crate. The tool catalogue, names, and JSON shapes will grow as more operations are exposed.

“Settling” = close to its 1.0 shape; “maturing” = the surface is broad and proven but still grows additively; “evolving” = expect the most movement; “new” = just landed, the surface and the empirically-validated CLI argv/JSON may still shift.

§MSRV policy

The minimum supported Rust version is 1.88 (edition 2024 needs 1.85, but the wrappers use let-chains, stabilised in 1.88). It is declared once in [workspace.package] as rust-version = "1.88" and inherited by every crate, so cargo build on an older toolchain fails early with a clear message — the contract is machine-checked, not just documented.

An MSRV bump is treated as a minor-version change (a 0.x minor today; a major after 1.0 if a consumer pins an older toolchain) and is called out in the changelog. We bump the MSRV only when a dependency or a genuinely useful language feature requires it — not casually.

§Public-API review checklist (the 1.0 gate)

Before any crate is tagged 1.0, its public surface is reviewed against the invariants this workspace already holds (most are enforced today; 1.0 makes them a promise):

  • Trait object-safety & mockability. Every public trait stays object-safe (no generic methods, no nested-reference lifetimes — owned &[String]/Option<String>, not &[&str]/Option<&str>), so &dyn Api and async-trait keep working. The wrapper traits (GitApi/JjApi/ GitHubApi/GitLabApi/GiteaApi) are additionally mockall-friendly: the mock feature generates a Mock*Api. The facade traits (VcsRepo, ForgeApi) deliberately carry no mock feature — they’re generated by a macro_rules! whose :ty signatures mockall::automock can’t parse — so the facades are tested over a fake runner (Repo::from_git / Forge::for_github), which is their documented test path anyway.
  • #[non_exhaustive] on returned types. Every struct/enum a consumer reads (DTOs, parsed results) is #[non_exhaustive] so a new field/variant isn’t a breaking change — except deliberate value types (Version) that callers legitimately construct.
  • Structured errors. Failures surface as processkit::Error variants (Exit/Timeout/Spawn/Parse), never a stringly-typed blob; the facade adds only repo-detection variants. Classifiers (is_merge_conflict, …) give intent without matching on internals.
  • Injection-safe by default. Caller strings in bare positional argv slots are guarded (reject_flag_like); flag-value slots are documented as exempt.
  • No leaked internals. Re-exports are explicit (no glob leaks); private parsers/helpers stay private; the cli_client! seam isn’t part of the surface.
  • Docs + tests. Every public method has a doc comment and at least a hermetic test pinning its argv/parse; the pure parsers are property-tested for panic-freedom; real-binary behaviour is covered by the #[ignore] integration suites (CI version-matrixes jj).

§See also

  • AGENTS.md — the release process, changelog curation, and dependency conventions.
  • Process model & errors — the error model the API review references.
  • ROADMAP.md6.12 and the remaining path-to-1.0 work.