From 1fbeeb52b8cb3834fcacd756b50089f021c89b74 Mon Sep 17 00:00:00 2001 From: slhx agent Date: Fri, 5 Jun 2026 09:49:30 +0200 Subject: [PATCH] docs(hemx): define v1 versioning policy Add a compact semver and upgrade policy for v1: stable beginner APIs, stable wire/runtime compatibility, advanced escape-hatch tier, breaking-change rules, upgrade-note template, and release checklist. req: abi/001 req: abi/002 req: abi/003 req: abi/004 req: abi/005 req: public_api/001 req: public_api/002 req: public_api/005 req: runtime/003 req: runtime/004 --- README.md | 1 + docs/recipes/deploy-versioning.md | 3 +- docs/versioning.md | 149 ++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 docs/versioning.md diff --git a/README.md b/README.md index eb93149..55b4a8b 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ fall back to a full page reload when possible. See `docs/recipes/deploy-versioni Before a v1 release, the semver policy and upgrade notes should explicitly state which surfaces are stable: beginner generated helpers and handler shapes; the wire/runtime ABI; and advanced escape hatches that may remain integration-level. +See `docs/versioning.md`. ## Examples diff --git a/docs/recipes/deploy-versioning.md b/docs/recipes/deploy-versioning.md index bfe3ec4..19c84dd 100644 --- a/docs/recipes/deploy-versioning.md +++ b/docs/recipes/deploy-versioning.md @@ -104,7 +104,8 @@ For v1, document changes in three buckets: Upgrade notes should explain what changed, whether generated code must be regenerated, whether `/hemx.js` must be rolled with the server, and what fallback -users see if an old page talks to a new server. +users see if an old page talks to a new server. Use `docs/versioning.md` as the +release-policy checklist. ## Deployment checklist diff --git a/docs/versioning.md b/docs/versioning.md new file mode 100644 index 0000000..30f4087 --- /dev/null +++ b/docs/versioning.md @@ -0,0 +1,149 @@ +# v1 versioning and upgrade policy + +hemx v1 should be boring to upgrade: beginner apps can rely on the generated +helper and handler model, while advanced escape hatches remain explicitly named +and easier to audit. This policy defines what must be stable for v1 and how to +ship breaking changes without hiding incompatibility behind runtime magic. req: abi/001 req: public_api/001 + +## Stability tiers + +### Stable beginner API + +These are the v1 normal path and require semver-major treatment for breaking +changes: + +- `#[hemx::surface]`, `#[hemx::app]`, `#[hemx::component]`, `#[hemx::handler]`, + and `#[hemx::form]` +- generated component helpers for slots, keyed partials, forms, handles, page + targets, class tokens, and events +- `hemx::page(...)` for page-boundary rendering +- tuple `IntoEffect` composition +- `Result` handlers with `IntoHandlerFailure` +- generated form commands such as `clear`, `reset`, `error`, and `focus` +- generated keyed commands such as `append`, `replace`, and `remove` + +A change is breaking if a production-shaped app like `examples/saas` must rewrite +normal handler/template code that was using those APIs correctly. req: examples/001 req: canonical_authoring/006 + +### Stable compatibility contract + +These must remain explicit and fail closed when incompatible: + +- Surface schema version consumed by `hemx_build` +- generated symbols and deterministic resource allocation inputs +- EffectBatch wire/schema ABI +- JavaScript runtime ABI +- build fingerprint inputs and mismatch behavior + +An incompatible wire/runtime change must bump the relevant ABI version and cause +old pages or old runtimes to refuse partial updates rather than silently applying +wrong effects. req: abi/002 req: abi/003 req: abi/004 req: failure/005 + +### Advanced escape hatches + +These are public but advanced. They may evolve faster, but every change still +needs a migration note and must not leak into beginner docs: + +- raw effects and batches +- manual registries +- low-level resource ids and raw targets +- raw HTML/render/target construction +- runtime hooks and SSE internals +- island internals and custom integration glue + +Advanced APIs are for integration crates, tests, migrations, or explicit leaf +boundaries. They are not a second beginner API. req: public_api/002 req: public_api/005 + +## What counts as breaking + +Breaking for the beginner API: + +- renaming generated helper methods or changing their return contracts +- requiring manual registry wiring for canonical apps +- requiring user-authored JavaScript or selector targeting for ordinary forms, + partial swaps, page swaps, or SSE/polling +- moving validation/error UI off generated form helpers +- changing handler argument inference so existing valid handlers stop compiling +- changing `Result` mapping so app errors no longer map at + the integration boundary + +Breaking for compatibility: + +- changing effect wire encoding without an ABI bump +- changing runtime target lookup semantics without a fingerprint/ABI bump +- changing generated id allocation inputs without a fingerprint change +- allowing mismatched server/runtime builds to apply partial updates + +Not breaking: + +- improving diagnostics while keeping spans and fixes user-facing +- adding generated helpers that are aliases around existing behavior when they + remove real friction +- adding new advanced escape hatches that are clearly named and isolated +- adding production recipes for providers outside core +- changing examples to better express the canonical path, when the documented API + remains compatible + +## Upgrade note template + +Every release with public API, generated ABI, runtime, or recipe changes should +include upgrade notes with this shape: + +````md +## Upgrade to hemx X.Y.Z + +### Who is affected +- Beginner app code: yes/no +- Generated helpers: yes/no +- Wire/runtime ABI: yes/no +- Advanced escape hatches: yes/no +- Recipes/examples only: yes/no + +### Required actions +- Regenerate generated code with `cargo check` or your normal build. +- Deploy server and `/hemx.js` from the same release if ABI/fingerprint changed. +- Update any renamed helpers or advanced calls listed below. + +### Compatibility behavior +- Old page + new server: reload/fail closed/compatible +- New page + old server: reload/fail closed/compatible +- Rolling deploy requirement: sticky release routing / normal routing + +### Migrations +- Before: ... +- After: ... + +### Verification +```sh +cargo run -p hemx-xtask -- test +cargo check --workspace +redgate health --strict +``` +```` + +## Release checklist + +Before tagging a v1-compatible release: + +- `examples/v0` and `examples/saas` compile and test without raw ids, raw effects, + selector targeting, manual registries, raw render/lower calls, or user-authored + UI JavaScript in the normal path. req: examples/004 req: examples/005 +- `docs/diagnostics.md` describes any new common error class in user language. + req: diagnostics/001 req: diagnostics/002 +- `docs/recipes/deploy-versioning.md` remains accurate for runtime asset and + fingerprint behavior. +- Any incompatible generated ABI/runtime change bumps the relevant ABI/fingerprint + inputs and has tests for fail-closed behavior. req: abi/005 +- Advanced APIs touched by the release are still named as escape hatches in docs. +- Upgrade notes state whether users must regenerate code, redeploy `/hemx.js`, or + change app code. + +## Policy for v1 cutover + +v1 is ready to cut only when the normal path can stay stable for the canonical +SaaS tutorial: hemplate templates, typed handlers, generated helpers, tuple +effects, result error mapping, page/push shape, explicit provider adapters, +plain CSS, and one island boundary. If stabilizing one of those surfaces would +require adding runtime negotiation, selector retargeting, a client state store, or +provider-specific core code, defer the feature or keep it advanced instead of +weakening the v1 contract. req: runtime/003 req: runtime/004 req: laws/004