Skip to content

pyvolca: enforce + document + preflight engine wire compatibility#147

Merged
ccomb merged 5 commits into
mainfrom
feat/pyvolca-wire-compat
Jun 22, 2026
Merged

pyvolca: enforce + document + preflight engine wire compatibility#147
ccomb merged 5 commits into
mainfrom
feat/pyvolca-wire-compat

Conversation

@ccomb

@ccomb ccomb commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Why

pyvolca decodes a wire whose shape changed with the activity_name / product_name rename, but no published engine emits that wire yet (last release v0.7.0). pip install pyvolca + Server.download() (which resolves the latest release) was therefore broken-by-default, with no version hint.

What

Compatibility is now carried by the engine's wireVersion (see the companion engine PR), not by version numbers — pyvolca and the engine version independently.

  • Runtime gatevolca._compat is the single source of truth (the wire this client speaks + the minimum engine it needs). The client checks once before its first call; Server.start() checks the engine it spawns and tears it down on a mismatch. get_version stays ungated so a bad engine is still inspectable, and VOLCA_SKIP_COMPAT_CHECK is a noisy opt-out.
  • Docs — a ## Compatibility section (visible on PyPI): a static pyvolca↔wire↔engine history table plus the policy. The one code-derived line is generated from volca._compat, with a drift test keeping it in sync.
  • Release preflightscripts/release_precheck.py answers "can I release pyvolca now?" locally: the version is new, the changelog records it, the tree is clean, and — the point — the engine release this pyvolca's wire requires is already tagged.

pyvolca stays 0.6.0: the wire policy carries compatibility, not the version number.

Verified: the test suite passes; against a live engine emitting wireVersion=1 a client is accepted, while a client requiring a newer wire is refused with a clear error; the preflight correctly reports NOT READY until an engine ≥ v0.8.0 is tagged.

ccomb added 5 commits June 22, 2026 17:57
pyvolca decodes a JSON wire whose shape changed with the activity_name/product_name rename, but nothing checked at runtime whether the engine actually speaks that wire — an older engine just produced an opaque decode error.

Add volca._compat as the single source of truth (the wire this client requires + the engine-version hint) and record the engine's wireVersion on ServerVersion. Gate operations on it: the client checks once before its first call; Server.start() checks the engine it spawns and tears it down on a mismatch. get_version stays ungated so a bad engine is still inspectable, and VOLCA_SKIP_COMPAT_CHECK is a noisy opt-out.

The README api-reference block is regenerated for the new ServerVersion field.
Add a Compatibility section to the README (so it shows on PyPI) and make the wire policy discoverable at install time: a static pyvolca <-> wire <-> engine history table plus the rule that wireVersion, not the version numbers, carries compatibility.

The one code-derived line (which wire this build speaks, which engine it needs) is generated from volca._compat into its own marker block so it can't drift from the policy. gen_api_md's splice is generalized to handle both the api-reference and compatibility blocks, and a mirror drift test keeps the committed block in sync in CI.
Add scripts/release_precheck.py — a local gate answering "can I release pyvolca now?" before the tag is pushed (pyvolca-release.yml only checks tag==version, and only after the push).

It verifies the version is new (vs the tag and PyPI), the changelog records it, the tree is clean, and — the point — that the engine release this pyvolca's wire requires (volca._compat.MIN_ENGINE_HINT) is already tagged, so a release can't strand users on a wire no published engine speaks. Green prints the exact tag commands; --no-tests skips the pytest+build leg.
refresh_stubs is the documented "engine was upgraded" path — the likeliest
place to meet a wire mismatch — yet it fetched and parsed the OpenAPI spec
without the one-shot gate _load_operations runs, so an incompatible engine
slipped through silently. Run _ensure_compatible first; it refuses before the
spec it couldn't decode is fetched. README api-reference block regenerated.
check_newer_than_pypi fell through to PASS whenever PyPI's latest didn't parse
as plain semver (a pre-release suffix makes _semver return None), asserting
"newer" on a comparison it never actually made. Return WARN when either side
is unparseable.
@ccomb ccomb merged commit a609fa0 into main Jun 22, 2026
10 checks passed
@ccomb ccomb deleted the feat/pyvolca-wire-compat branch June 22, 2026 23:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant